Setups

Loading packages and custom functions

# loading packages
# devtools::install_github("thomasp85/patchwork")
pacman::p_load(tidyverse, # tidy family and related pacakges below
               kableExtra, 
               gridExtra, # may not use this
               purrr,
               magrittr, # extending piping
               pander,   # nice tables
               metafor,  # package for meta-analysis
               MCMCglmm,  # Bayeisan mixed model package
               ggbeeswarm, # making bee-swarm plots possible
               plotly,     # interactive plots using ggplot2
               MuMIn,  # multi-model inference
               lme4,   # lmm & glmm (models)
               broom.mixed, # getting estimates from lmer + glmer objects
               performance, # getting R2 from lmer + glmer objects
               png,         # reading png files
               grid,        # graphic layout manipulation
               patchwork,   # putting ggplots together - you need to install via devtool
               here         # making reading files easy
               #lmerTest,   # more functions for lme4
               #mi,      # missing data analysis
               #betareg   # dependence of the above
)

Custom functions

We have 5 custom functions named : p_to_Zr(),I2(), R2(), get_est(), get_pred(), and cont_gen(), all of which are used later (see below for their functionality) and the code is included here.

# coustm functions

#' Title: getting Zr and its sampling variance from p value 
#'
#' @param data: data frame 
#' @param pval: p value
#' @param N: sample size (N: the number of species ) and the degrees of freedom df = N - 2
#'
#' @return
#' @export
#'
#' @examples
p_to_Zr <- function(data, pval, N) {
    
    # turning them into strings
    pval <- data[[deparse(substitute(pval))]]
    N <- data[[deparse(substitute(N))]]
    
    # getting t values
    tval <- -qt(pval, N - 2)
    rval <- tval/sqrt((tval^2) + (N - 2))
    
    # define Zr function Zr <- 0.5*(log(1 + rval) - log(1 - rval)); the same as below
    # r <-tanh(Zr) # turning Zr to r
    Zr <- atanh(rval)
    
    # getting Var(Zr)
    VZr <- 1/(N - 3)
    
    # putting all together
    Zrs <- tibble(rval, Zr, VZr)
    data <- bind_cols(data, Zrs)
}

# coverting back Zr to r Just use 'psych' pacakge - fisherz2r(z) -
# <http://personality-project.org/r/psych/help/fisherz.html> or this will do : r
# to Zr is tanh(r)!!

# Functions for processing


# General modeling functions Functions for I2

#' Title Function to obtain total and separate I2 from multilevel-meta-analytic model
#'
#' @param model 
#' @param method 
#'
#' @return
#' @export
#'
#' @examples
I2 <- function(model, method = c("Wolfgang", "Shinichi")) {
    
    ## evaluate choices
    method <- match.arg(method)
    
    # Wolfgang's method
    if (method == "Wolfgang") {
        W <- solve(model$V)
        X <- model.matrix(model)
        P <- W - W %*% X %*% solve(t(X) %*% W %*% X) %*% t(X) %*% W
        I2_total <- sum(model$sigma2)/(sum(model$sigma2) + (model$k - model$p)/sum(diag(P)))
        I2_each <- model$sigma2/(sum(model$sigma2) + (model$k - model$p)/sum(diag(P)))
        names(I2_each) = paste0("I2_", model$s.names)
        
        # putting all together
        I2s <- c(I2_total = I2_total, I2_each)
        
        # or my way
    } else {
        # sigma2_v = typical sampling error variance
        sigma2_v <- sum(1/model$vi) * (model$k - 1)/(sum(1/model$vi)^2 - sum((1/model$vi)^2))
        I2_total <- sum(model$sigma2)/(sum(model$sigma2) + sigma2_v)  #s^2_t = total variance
        I2_each <- model$sigma2/(sum(model$sigma2) + sigma2_v)
        names(I2_each) = paste0("I2_", model$s.names)
        
        # putting all together
        I2s <- c(I2_total = I2_total, I2_each)
    }
    return(I2s)
}

# test <- dataset$fit4.1[[3]] I2(test, method = 'Wolfgang') I2(test, method =
# 'Shinichi')


#' Title: R2 based on Nakagawa & Schielzeth 2013
#'
#' @param model 
#'
#' @return
#' @export
#'
#' @examples
R2 <- function(model) {
    warning("Conditional R2 is not meaningful and the same as marginal R2\n")
    
    # fixed effect variance
    fix <- var(as.numeric(as.vector(model$b) %*% t(as.matrix(model$X))))
    
    # marginal
    R2m <- fix/(fix + sum(model$sigma2))
    R2
    # Rm <- round(100*R2m, 3)
    
    # conditional
    R2c <- (fix + sum(model$sigma2) - model$sigma2[length(model$sigma2)])/(fix + 
        sum(model$sigma2))
    
    R2s <- c(R2_marginal = R2m, R2_coditional = R2c)
    return(R2s)
}


#' Title: the function to get estimates from rma objects (metafor)
#'
#' @param model: rma.mv object 
#' @param mod: the name of a moderator 
get_est <- function(model, mod = " ") {
    
    name <- as.factor(str_replace(row.names(model$beta), mod, ""))
    estimate <- as.numeric(model$beta)
    lowerCL <- model$ci.lb
    upperCL <- model$ci.ub
    
    table <- tibble(name = name, estimate = estimate, lowerCL = lowerCL, upperCL = upperCL)
}


#' Title: the function to get prediction intervals (crediblity intervals) from rma objects (metafor)
#'
#' @param model: rma.mv object 
#' @param mod: the name of a moderator 
get_pred <- function(model, mod = " ") {
    name <- as.factor(str_replace(row.names(model$beta), mod, ""))
    len <- length(name)
    
    if (len != 1) {
        newdata <- matrix(NA, ncol = len, nrow = len)
        for (i in 1:len) {
            # getting the position of unique case from X (design matrix)
            pos <- which(model$X[, i] == 1)[[1]]
            newdata[, i] <- model$X[pos, ]
        }
        pred <- predict.rma(model, newmods = newdata)
    } else {
        pred <- predict.rma(model)
    }
    lowerPR <- pred$cr.lb
    upperPR <- pred$cr.ub
    
    table <- tibble(name = name, lowerPR = lowerPR, upperPR = upperPR)
}

# Here are links for how to do confidence regions for rma.mv regression lines
# https://www.rdocumentation.org/packages/metafor/versions/1.9-9/topics/predict.rma
# https://stackoverflow.com/questions/50804464/out-of-sample-prediction-for-rma-object-in-metafor


#' Title: Contrast name geneator
#'
#' @param name: a vector of character strings
cont_gen <- function(name) {
    combination <- combn(name, 2)
    name_dat <- t(combination)
    names <- paste(name_dat[, 1], name_dat[, 2], sep = "-")
    return(names)
}

Appendix S1: Supplementary Methods

The Cophylogeny Dataset

Table of the dataset

Below is the dataset used for our meta-analysis, followed by explanations of 24 variables extracted from the papers included (not all variables were used for our analyses; variables which were neither ‘directly’ nor ‘indirectly’ used in our analyses are indicated by *).

Table S1.2

The meta-analytic dataset of this study.

# getting the data and formating some variables (turning chraracter vectors to
# factors)
full_data <- read_csv(here("data/2021-09-01-source-data-dat.csv"), na = "NA") %>% 
    mutate_if(is.character, as.factor)

# dataset to compare the same cophylogenies between the two methods

full_pair <- read_csv(here("data/2020-08-12-paried.csv"), na = "NA") %>% mutate_if(is.character, 
    as.factor)

# making a scrollable table
kable(full_data, "html") %>% kable_styling("striped", position = "left") %>% scroll_box(width = "100%", 
    height = "500px")
authors year host_tax_broad symbiont_tax_broad symbiont_euk symbiosis endo_or_ecto mode_of_transmission_broad mode_of_transmission_fine Visiting_symbiont? host_tips_linked host_tips_linked_corrected host_genera total_host_symbioint_links host_range_link_ratio host_range_taxonomic_breadth symbiont_tips_linked symbiont_genera no_randomizations p_value method
Althoff_et_al_2012 2012 Plant Invert y Mutualist Ecto horizontal autonomous visitor 24 24 1 40 2.00 1.35 20 1 1000 0.00100 Parafit
Althoff_et_al_2012 2012 Plant Invert y Mutualist Ecto horizontal autonomous visitor 24 24 1 38 2.24 1.53 17 1 1000 0.00100 Parafit
Arab_et_al_2019 2019 Invert Microbe n Mutualist Endo vertical vertical resident 55 55 52 55 1.00 1.00 55 1 999 0.00100 Parafit
Ballinger_et_al_2018 2018 Invert Microbe n Mutualist Endo vertical vertical resident 11 11 1 12 1.00 1.00 12 1 999 0.07000 Parafit
Banks_et_al_2006 2006 Vert Invert y Parasite Ecto both contact resident 18 18 6 30 2.00 1.60 15 2 10000 0.00100 Parafit
Bayerlova_2009 2009 Vert Microbe n Parasite Endo horizontal contact resident 21 21 14 31 1.55 1.45 20 1 9999 0.00040 Parafit
Bellec_et_al_2014 2014 Plant Microbe n Parasite Endo horizontal contact resident 22 22 3 133 2.61 1.65 51 1 999 0.00100 Parafit
Bruyndonckxx_et_al_2009 2009 Vert Invert y Parasite Ecto both contact resident 20 20 7 21 1.91 2.27 11 2 9999 0.00300 Parafit
Caraguel_et_al__2007 2007 Microbe Microbe y Mutualist Endo vertical vertical resident 6 6 1 6 1.00 1.00 6 1 9999 0.00100 Parafit
Carneiro_et_al_2018 2018 Vert Microbe n Parasite Endo horizontal body fluid resident 26 26 21 26 1.00 1.00 26 1 100000 0.01000 Parafit
Catanach_et_al_2018 2018 Vert Invert y Parasite Ecto both contact resident 54 28 5 44 1.07 0.93 41 30 999 0.00100 Parafit
Chen_et_al_2017 2017 Invert Microbe n Mutualist Endo vertical vertical resident 50 50 11 50 1.00 1.00 50 1 999 0.00100 Parafit
Choi_&_Thines_2015 2015 Plant Microbe y Parasite Endo horizontal autonomous resident 63 63 28 63 1.00 1.00 63 3 999 0.00100 Parafit
Conord_et_al_2008 2008 Invert Microbe n Mutualist Endo vertical vertical resident 14 14 10 14 1.00 1.00 14 1 999 0.00900 Parafit
Cornuault_et_al_2012 2012 Vert Microbe y Parasite Endo horizontal vector resident 8 8 1 23 1.28 1.17 18 1 9999 0.03500 Parafit
Cruaud_et_al_2012 2012 Plant Invert y Mutualist Endo horizontal autonomous resident 200 200 1 200 1.00 1.00 200 20 9999 0.01000 Parafit
Cui_et_al_2014 2014 Vert Microbe n Parasite Endo horizontal body fluid resident 46 46 46 NA NA NA 61 NA 99999 0.23300 Parafit
Deng_et_al_2013 2013 Invert Invert y Parasite Endo horizontal autonomous resident 7 7 4 10 1.00 1.00 10 2 999 0.01602 Parafit
Desdevises_et_al_2002 2002 Vert Invert y Parasite Ecto horizontal autonomous resident 14 14 11 39 1.95 1.65 20 2 999 0.26000 Parafit
Dhami_et_al_2013 2013 Invert Microbe n Mutualist Endo vertical vertical resident 42 42 NA 42 1.00 1.00 42 4 999 0.00100 Parafit
Dona_2018 2018 Vert Invert y Parasite Ecto both contact resident 14 14 13 15 1.00 1.00 15 1 100000 0.01000 Parafit
Dona_2018 2018 Vert Invert y Parasite Ecto both contact resident 42 42 29 44 1.00 1.00 44 1 100000 0.01000 Parafit
Dowie_et_al_2016 2016 Microbe Plant y Parasite Endo horizontal environmental resident 4 4 1 9 2.25 1.50 4 1 9999 0.00100 Parafit
Du_Toit_et_al_2013 2013 Vert Invert y Parasite Ecto both contact resident 4 4 1 14 1.17 1.17 12 1 10000 0.88000 Parafit
Endara_et_al_2017 2017 Plant Invert y Parasite Ecto horizontal autonomous visitor 18 18 1 29 1.00 2.17 29 NA 100 0.70000 Parafit
Endara_et_al_2017 2017 Plant Invert y Parasite Ecto horizontal autonomous visitor 10 10 1 18 1.50 1.25 12 NA 100 0.90000 Parafit
Endara_et_al_2017 2017 Plant Invert y Parasite Ecto horizontal autonomous visitor 14 14 1 18 1.20 1.13 15 NA 100 0.74000 Parafit
Endara_et_al_2018 2018 Plant Invert y Parasite Endo horizontal autonomous resident 44 30 1 45 1.18 1.03 38 NA 9999 0.01500 Parafit
FerrerParis_et_al_2013 2013 Plant Invert y Parasite Ecto horizontal autonomous visitor 64 64 NA 112 2.73 5.20 41 NA 999 0.15700 Parafit
FraijaFernandez_et_al_2016 2016 Vert Invert y Parasite Endo horizontal trophic resident 31 31 24 50 5.56 3.67 9 6 999 0.00100 Parafit
Garamszegi_2009 2009 Vert Microbe y Parasite Endo horizontal vector resident 23 23 23 43 2.39 2.56 18 1 1000 0.00100 Parafit
Garcia_&_Hayman_2016 2016 Vert Microbe y Parasite Endo horizontal trophic resident 22 22 22 36 1.33 1.96 27 1 999 0.01000 Parafit
Gavotte_et_al_2007 2007 Microbe Microbe n Parasite Endo both NA resident 33 33 1 51 0.93 1.00 55 1 10000 0.13190 Parafit
Goker_et_al_2011 2011 Microbe Microbe n Parasite Endo NA NA resident 8 8 8 8 1.00 1.00 8 1 9999 0.09780 Parafit
Gomard_et_al_2016 2016 Vert Microbe n Parasite Endo horizontal NA resident 12 12 11 26 1.00 1.00 26 1 999 0.09000 Parafit
Gottschling_et_al_2011 2011 Vert Microbe n Parasite Endo horizontal contact resident 43 43 40 78 1.00 1.00 78 30 9999 0.00010 Parafit
Graca_et_al_2018 2018 Vert Invert y Parasite Endo horizontal autonomous resident 9 9 7 18 1.29 1.29 14 1 10000 0.00010 Parafit
Hall_et_al__2016 2016 Invert Microbe n Mutualist Endo vertical vertical resident 37 37 18 37 1.00 1.00 37 1 10000 0.00100 Parafit
Hall_et_al__2016 2016 Invert Microbe n Mutualist Endo vertical vertical resident 20 20 9 20 1.00 1.00 20 1 10000 0.38700 Parafit
Hammer_et_al_2010 2010 Vert Invert y Parasite Ecto both contact resident 23 23 6 23 1.10 1.00 21 1 999 0.00100 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert y Parasite Endo horizontal autonomous resident 11 11 2 11 1.38 1.13 8 2 999 0.12900 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert y Parasite Endo horizontal autonomous resident 6 6 2 6 1.50 1.25 4 2 999 0.19500 Parafit
Hammerlinck_et_al_2016 2016 Invert Invert y Parasite Endo horizontal autonomous resident 7 7 2 7 1.00 1.00 7 2 999 0.04200 Parafit
Hembry_et_al_2013 2013 Plant Invert y Mutualist Ecto horizontal autonomous visitor 37 37 1 35 1.00 1.00 35 1 999 0.01700 Parafit
Herrera__et_al_2016 2016 Microbe Microbe y Parasite Endo horizontal environmental resident 13 13 9 13 1.00 1.00 13 3 999 0.00500 Parafit
Hewitt_et_al_2019 2019 Vert Invert y Parasite Ecto horizontal autonomous resident 178 178 79 495 7.17 3.30 69 35 999 0.00100 Parafit
Hoglund_et_al_2003 2003 Vert Invert y Parasite Endo horizontal trophic resident 8 8 8 10 2.00 2.40 5 1 10000 0.09800 Parafit
Holzer_et_al_2018 2018 Invert Invert y Parasite Endo horizontal environmental resident 23 23 22 39 1.00 1.00 39 21 1000 0.00100 Parafit
Holzer_et_al_2018 2018 Vert Invert y Parasite Endo horizontal environmental resident 69 69 62 101 1.00 1.00 101 15 1000 0.00100 Parafit
Holzer_et_al_2018 2018 Vert Invert y Parasite Endo horizontal environmental resident 69 69 58 75 1.00 1.00 75 21 1000 0.00100 Parafit
Hughes_et_al_2007 2007 Vert Invert y Parasite Ecto both contact resident 18 18 6 18 1.06 1.00 17 1 999 0.00010 Parafit
Huyse_&_Volckaert_2005 2005 Vert Invert y Parasite Ecto horizontal autonomous resident 8 8 3 22 1.29 1.29 17 1 999 0.09500 Parafit
Irwin_et_al_2012 2012 Vert Microbe n Parasite Endo horizontal contact resident 21 21 14 31 1.55 1.85 20 NA 9999 0.00040 Parafit
Jenkins_et_al_2012 2012 Vert Microbe y Parasite Endo horizontal autonomous resident 52 52 40 138 1.45 NA 95 1 999 0.00100 Parafit
Jesovnik_et_al_2017 2017 Invert Microbe y Mutualist Ecto both environmental resident 32 6 1 6 1.00 1.00 6 1 999 0.02900 Parafit
Jousselin_et_al_2008 2008 Plant Invert y Mutualist Endo horizontal autonomous resident 15 15 1 15 1.07 1.07 14 6 9999 0.00300 Parafit
Jousselin_et_al_2008 2008 Plant Invert y Parasite Endo horizontal autonomous resident 13 13 1 13 1.00 1.00 13 1 9999 0.02000 Parafit
Jousselin_et_al_2008 2008 Plant Invert y Parasite Endo horizontal autonomous resident 16 16 1 18 1.06 1.06 17 2 9999 0.00100 Parafit
Jousselin_et_al_2008 2008 Plant Invert y Parasite Endo horizontal autonomous resident 13 13 1 14 1.00 1.00 14 1 9999 0.00300 Parafit
Jousselin_et_al_2009 2009 Invert Microbe n Mutualist Endo vertical vertical resident 55 22 1 22 1.00 1.00 22 1 9999 0.00100 Parafit
Kaltenpoth_et_al_2014 2014 Invert Microbe n Mutualist Endo vertical vertical resident 39 39 2 41 1.00 1.00 41 1 1000 0.00100 Parafit
Kawakita_&_Kato_2009 2009 Plant Invert y Mutualist Ecto horizontal autonomous visitor 10 10 7 10 1.00 1.00 10 1 100 0.39000 Parafit
Kawakita_et_al_2004 2004 Plant Invert y Mutualist Ecto horizontal autonomous visitor 18 18 1 18 1.00 1.00 18 1 999 0.00500 Parafit
Kawazoe_et_al_2008 2008 Invert Invert y Mutualist Ecto vertical vertical resident 4 4 1 5 1.25 1.25 4 1 9999 0.00010 Parafit
Kolsch_&__Pedersen_2010 2010 Invert Microbe n Mutualist Endo vertical vertical resident 41 41 7 41 1.00 1.00 41 1 9999 0.00100 Parafit
Krasnov_&_Shenbrot_2013 2013 Vert Invert y Parasite Ecto horizontal contact resident 21 21 8 62 3.26 4.37 19 7 999 0.16000 Parafit
Krumbholz_et_al_2009 2009 Vert Microbe n Parasite Endo horizontal NA resident 13 13 13 18 1.00 1.00 18 1 999999 0.49460 Parafit
Ku_&_Hu_2014 2014 Plant Microbe n Mutualist Endo vertical vertical resident 11 11 1 11 1.00 1.00 11 1 9999 0.02000 Parafit
Lanterbecq_et_al_2010 2010 Invert Invert y Parasite Endo/Ecto horizontal contact resident 16 16 12 16 1.00 1.00 16 5 1000 0.01300 Parafit
Latinne_et_al_2018 2018 Vert Microbe y Parasite Endo horizontal enviromental resident 15 15 6 19 3.17 2.00 6 1 999 0.00900 Parafit
Lauber_et_al_2017 2017 Vert Microbe n Parasite Endo horizontal autonomous resident 30 30 28 30 0.88 1.00 34 8 10000 0.00010 Parafit
Lauron_et_al_2015 2015 Vert Microbe y Parasite Endo horizontal vector resident 18 18 8 83 1.80 NA 46 1 1000 0.66000 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 14 14 11 38 1.00 1.00 38 1 999 0.00100 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 4 4 4 20 1.00 1.00 20 1 999 0.00100 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 14 14 12 19 1.00 1.00 19 1 999 0.85800 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 9 9 8 13 1.00 1.00 13 1 999 0.02900 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 35 35 22 119 1.09 1.17 109 1 999 0.00010 Parafit
Lei_&_Olival_2014 2014 Vert Microbe n Parasite Endo horizontal environmental resident 6 6 5 7 1.00 1.00 7 1 999 0.75870 Parafit
LewisRogers_&_Crandall_2009 2009 Vert Microbe n Parasite Endo horizontal contact resident 6 6 NA 27 1.00 1.00 27 11 999 0.47000 Parafit
Li_et_al_2017 2017 Plant Microbe y Parasite Endo horizontal vector Resident 12 12 9 12 1.71 2.00 7 1 999 0.50505 Parafit
Li_et_al_2017 2017 Plant Microbe y Parasite Endo horizontal autonomous resident 12 12 9 12 1.71 1.57 7 1 999 0.50505 Parafit
Li_et_al_2018 2018 Vert Invert y Parasite Endo horizontal trophic resident 68 68 34 129 1.45 NA 89 89 100000 0.00100 Parafit
Light_&_Hafner_2008 2008 Vert Invert y Parasite Ecto both contact resident 44 21 4 21 1.00 1.00 21 1 999 0.00100 Parafit
Liu_et_al_2016 2016 Plant Microbe y Parasite Endo NA environmental resident 13 13 10 44 1.57 2.71 28 28 9999 0.02510 Parafit
Liu_et_al_2016 2016 Plant Microbe y Parasite Endo NA environmental resident 19 19 16 76 3.30 3.22 23 23 9999 0.02030 Parafit
Maneesakorn_et_al_2011 2011 Invert Microbe n Mutualist Endo vertical vertical resident 12 12 1 12 1.00 1.00 12 1 999 0.00100 Parafit
Martinez_et_al_2011 2011 Invert Microbe y Parasite Endo horizontal vector resident 16 16 1 22 2.44 1.56 9 1 999 0.07500 Parafit
Martinez_San_udo_&_Girolami_2009 2009 Invert Microbe n Mutualist Endo vertical vertical resident 19 19 10 19 1.12 1.18 17 5 999 0.00300 Parafit
Matthews_et_al_2018 2018 Vert Invert y Parasite Ecto both contact resident 12 12 6 33 1.00 0.58 33 1 99900 0.00400 Parafit
Mattiucci_&_nascetti_2008 2008 Vert Invert y Parasite Endo horizontal trophic resident 7 7 15 12 1.33 1.78 9 1 100 0.05000 Parafit
Mazzon_et_al_2010 2010 Invert Microbe n Mutualist Endo vertical vertical resident 17 17 10 17 1.06 1.13 16 3 999 0.00700 Parafit
McFrederick_&_Taylor_2013 2013 Invert Invert y NA Ecto vertical vertical resident 7 7 3 7 1.00 1.00 7 1 10000 0.00600 Parafit
McKee_et_al_2016 2016 Vert Microbe n Parasite Endo horizontal vector resident 66 66 42 184 1.06 1.09 173 1 10000 0.00010 Parafit
McLeish_&_Van_Noort_2012 2012 Plant Invert y Mutualist Endo horizontal autonomous resident 26 26 1 65 1.00 1.00 65 6 9999 0.18000 Parafit
Megia-palma_et_al_2018 2018 Vert Microbe y Parasite Endo horizontal vector resident 16 16 8 23 1.53 1.27 15 8 999 0.00400 Parafit
Mehdiabadi_et_al_2012 2012 Invert Microbe y Mutualist Ecto both environmental resident 99 11 1 11 1.00 1.00 11 1 999 0.00100 Parafit
Mendlova_et_al_2012 2012 Vert Invert y Parasite Ecto horizontal autonomous resident 6 6 5 34 1.17 1.21 29 2 999 0.02400 Parafit
Merville_et_al._2013 2013 Invert Microbe n Mutualist Endo vertical vertical resident 9 9 1 9 1.00 1.00 9 1 999 0.00350 Parafit
Millanes_et_al_2014 2014 Microbe Microbe y Parasite Endo both environmental resident 16 16 2 16 1.00 1.00 16 1 999 0.23600 Parafit
Miyaki_et_al_2016 2016 Vert Microbe n Mutualist Endo horizontal environmental resident 8 8 4 54 3.18 2.24 17 1 999 0.00100 Parafit
Mondo_et_al_2012 2012 Microbe Microbe n Mutualist Endo vertical vertical resident 55 5 2 5 1.00 1.00 5 1 10000 0.00010 Parafit
Nouioui_et_al_2014 2014 Plant Microbe n Mutualist Endo horizontal vector resident 9 9 1 20 1.00 1.00 20 1 9999 0.33000 Parafit
Patra_et_al_2018 2018 Vert Invert y Parasite Endo horizontal environmental resident 24 24 24 31 1.00 1.00 31 1 999 0.00100 Parafit
Pellissier_et_al_2013 2013 Plant Invert y Parasite Ecto horizontal autonomous visitor 104 104 NA NA NA NA 97 NA 10000 0.00010 Parafit
Perkins_2010 2010 Vert Invert y Parasite Endo horizontal autonomous resident 61 61 50 75 1.00 1.00 75 NA 9999 0.92600 Parafit
Peterson_et_al_2010 2010 Plant Microbe y Parasite Endo horizontal environmental resident 11 11 1 25 2.08 1.58 12 1 9999 0.00010 Parafit
Polme_et_al_2014.pdf 2014 Plant Microbe n Mutualist Endo horizontal vector resident 22 22 1 NA NA NA 43 1 999 0.00100 Parafit
Quek_et_al_2004 2004 Plant Invert y Mutualist Ecto horizontal autonomous resident 9 9 1 19 1.90 1.50 10 1 999 0.77900 Parafit
Ramasindrazana_et_al_2017 2017 Vert Invert y Parasite Ecto both contact resident 15 15 6 26 2.89 1.78 9 5 999 0.00100 Parafit
Ricklefs_et_al_2004 2004 Vert Microbe y Parasite Endo horizontal vector resident 44 44 1 121 1.86 NA 65 2 100 0.63000 Parafit
Riess_et_al_2018 2018 Plant Microbe Y Parasite Endo horizontal autonomous resident 11 11 5 11 1.00 1.00 11 2 9999 0.26400 Parafit
Savio_2011 2011 Invert Microbe n Mutualist Endo horizontal NA resident 17 17 10 17 1.00 1.00 17 3 999 0.00700 Parafit
Schardl_et_al_2008 2008 Plant Microbe y Mutualist Endo both NA resident 25 25 16 25 0.96 1.00 26 2 1000 0.00100 Parafit
Sibbald_et_al_2017 2017 Microbe Microbe y Mutualist Endo horizontal environmental resident 7 7 1 7 1.00 1.00 7 1 9999 0.00010 Parafit
Simkova_et_al_2013 2013 Vert Invert y Parasite Ecto horizontal autonomous resident 5 5 1 21 1.00 1.00 21 1 999 0.01300 Parafit
Singh_et_al_2016 2016 Microbe Plant y Mutualist Endo horizontal environmental resident 23 23 1 28 1.40 1.20 20 1 9999 0.00020 Parafit
Singh_et_al_2017 2017 Microbe Plant y Mutualist Endo vertical vertical resident 23 17 1 25 1.25 1.15 20 1 9999 0.00020 Parafit
Sontowski_et_al_2015 2015 Invert Microbe n Mutualist Endo vertical vertical resident 14 14 4 14 1.00 1.00 14 1 100000 0.00300 Parafit
Sorenson_et_al_2004 2004 Vert Vert y Parasite Ecto horizontal autonomous resident 33 33 10 34 1.62 1.43 21 1 1000 0.00100 Parafit
Souza_et_al_2018 2018 Vert Microbe n Parasite Endo both body fluid resident 8 8 8 19 1.06 1.00 18 1 999 0.00500 Parafit
Stireman_et_al_2010 2010 Plant Invert y Parasite Endo horizontal autonomous resident 15 15 10 39 1.39 1.25 28 1 9999 0.00080 Parafit
Sudakaran_et_al_2015 2015 Invert Microbe n Mutualist Endo NA NA resident 16 16 7 22 1.00 1.00 22 1 1000 0.97800 Parafit
Sudakaran_et_al_2015 2015 Invert Microbe n Mutualist Endo NA NA resident 14 14 6 26 1.00 1.00 26 1 1000 0.97400 Parafit
Summers_&_Rouse_2014 2014 Invert Invert y Parasite Endo/Ecto horizontal autonomous resident 53 53 36 78 1.13 1.23 69 10 9999 0.00050 Parafit
Susoy_&_Herrmann_2014 2014 Invert Invert y Mutualist Ecto vertical vertical resident 35 35 7 37 1.42 1.31 26 1 9999 0.00010 Parafit
Swafford_&_Bond_2010 2010 Invert Invert y Parasite Ecto horizontal contact resident 7 7 1 7 1.00 1.00 7 1 9999 0.31900 Parafit
Sweet_&_Johnson_2018 2018 Vert Invert y Parasite Ecto both contact resident 13 13 4 14 2.80 1.80 5 1 100000 0.00500 Parafit
Sweet_et_al_2016 2016 Vert Invert y Parasite Ecto both contact resident 52 52 25 57 1.33 1.21 43 1 100000 0.00001 Parafit
Sweet_et_al_2016 2016 Vert Invert y Parasite Ecto both contact resident 52 52 25 58 1.18 1.14 49 4 100000 0.00001 Parafit
Sweet_et_al_2017 2017 Vert Invert y Parasite Ecto both contact resident 12 12 5 15 1.15 1.23 13 3 999 0.06900 Parafit
Sweet_et_al_2018a 2018 Vert Invert y Parasite Ecto both contact resident 259 259 163 283 1.63 1.61 174 11 9999 0.00010 Parafit
Sweet_et_al_2018b 2018 Vert Invert y Parasite Ecto both contact resident 11 11 4 13 1.86 1.43 7 1 100000 0.00500 Parafit
Tao_et_al_2013 2013 Vert Microbe n Parasite Endo horizontal NA resident 7 7 7 10 1.00 1.00 10 1 99999 0.17592 Parafit
Toju_et_al_2013 2013 Invert Microbe n Mutualist Endo vertical vertical resident 27 27 4 27 1.00 1.00 27 1 99999 0.00001 Parafit
Urban_&_Cryan_2012 2012 Invert Microbe n Mutualist Endo vertical vertical resident 30 30 29 30 1.00 1.00 30 1 1000 0.00100 Parafit
Urban_&_Cryan_2012 2012 Invert Microbe n Mutualist Endo vertical vertical resident 40 40 38 40 1.00 1.00 40 1 1000 0.00300 Parafit
Viale_et_al_2015 2015 Invert Microbe n Mutualist Endo vertical vertical resident 23 23 1 23 1.00 1.00 23 1 9999 0.00100 Parafit
Won_et_al_2008 2008 Invert Microbe n Mutualist Endo horizontal contact resident 15 15 5 15 1.00 1.00 15 1 100 0.37000 Parafit
Xu_et_el_2017 2017 Invert Microbe n Mutualist Endo vertical vertical resident 20 20 8 20 1.00 1.00 20 1 999 0.00100 Parafit
Zhang_et_al_2017 2017 Invert Microbe n Mutualist Endo vertical vertical resident 44 44 24 44 1.00 1.00 44 1 100000 0.00001 Parafit
Badets_et_al_2011 2011 Vert Invert y Parasite Endo horizontal autonomous resident 17 17 13 17 1.00 1.00 17 4 1000 0.01000 TreeMap
Banks_et_al_2006 2006 Vert Invert y Parasite Ecto both contact resident 18 18 6 30 2.00 1.60 15 2 1000 0.01000 TreeMap
Bochkov_et_al_2011 2011 Vert Invert y Parasite Ecto both contact resident 6 6 NA 9 1.00 1.00 9 6 100 0.01000 TreeMap
Charleston_&_Perkins_2003 2003 Vert Microbe y Parasite Endo horizontal vector resident 9 9 1 9 1.00 1.00 9 1 100 0.03000 TreeMap
Charleston_&_Robertson_2002 2002 Vert Microbe n Parasite Endo horizontal body fluid resident 12 12 12 12 1.00 1.00 12 1 1000 0.01500 TreeMap
Chauvatcharin_et_al_2006 2006 Microbe Microbe n Parasite Endo both NA resident 14 14 7 15 1.07 1.00 14 1 1000 0.33100 TreeMap
Clark_et_al_2000 2000 Invert Microbe n Mutualist Endo vertical vertical resident 17 17 4 17 1.00 1.00 17 1 1000 0.00100 TreeMap
Clayton_&_Johnson_2003 2003 Vert Invert y Parasite Ecto both contact resident 13 13 6 14 1.08 1.15 13 1 10000 0.00060 TreeMap
Clayton_&_Johnson_2003 2003 Vert Invert y Parasite Ecto both contact resident 13 13 6 16 1.60 1.50 10 1 10000 0.15300 TreeMap
Cui_et_al_2012 2012 Vert Microbe n Parasite Endo horizontal body fluid resident 7 7 3 7 1.00 1.00 7 7 10000 0.36600 TreeMap
Dabert_2001__ 2001 Vert Invert y Parasite Ecto both contact resident 21 21 12 22 1.00 1.00 22 9 10000 0.00100 TreeMap
Deng_et_al_2013 2013 Invert Invert y Parasite Endo horizontal autonomous resident 7 7 4 10 1.00 1.00 10 2 999 0.53000 TreeMap
Desai_et_al_2010 2010 Microbe Microbe n Mutualist Ecto both contact resident 9 9 2 8 0.89 1.00 9 1 1000 0.00100 TreeMap
Desdevises_et_al_2002 2002 Vert Invert y Parasite Ecto horizontal autonomous resident 14 14 11 39 1.95 1.65 20 2 999 0.31700 TreeMap
Downie_&_Gullan_2005 2005 Invert Microbe n Mutualist Endo vertical vertical resident 21 21 16 21 1.00 1.00 21 1 1000 0.00100 TreeMap
Erpenbeck_et_al_2002 2002 Invert Microbe n Mutualist Endo vertical vertical resident 6 6 5 6 1.00 1.00 6 1 10000 0.02000 TreeMap
Etherington_et_al_2006 2006 Vert Microbe n Parasite Endo horizontal contact resident 7 7 7 8 1.00 1.00 8 1 1000 0.01000 TreeMap
Farrell_1998 1998 Plant Invert y Parasite Ecto horizontal autonomous resident 21 21 2 21 1.00 1.00 21 6 1000 0.07000 TreeMap
Gottschling_et_al_2011 2011 Vert Microbe n Parasite Endo horizontal contact resident 43 43 40 78 1.00 1.00 78 30 1000 0.00100 TreeMap
Hendricks_et_al_2013 2013 Vert Invert y Parasite Ecto both contact resident 19 19 17 20 1.25 1.25 16 1 1000 0.02100 TreeMap
Hosokawa_et_al_2006 2006 Invert Microbe n Mutualist Endo vertical vertical resident 7 7 3 7 1.00 1.00 7 1 1000 0.00100 TreeMap
Hugot_1999 1999 Vert Invert y Parasite Endo horizontal trophic resident 10 10 9 11 1.00 1.00 11 6 1000 0.00100 TreeMap
Hugot_et_al_2003 2003 Vert Microbe y Parasite Endo horizontal contact resident 19 19 12 19 1.00 1.00 19 1 1000 0.00100 TreeMap
Huyse_&_Volckaert_2005 2005 Vert Invert y Parasite Ecto horizontal autonomous resident 8 8 3 22 1.29 1.29 17 1 100 0.02000 TreeMap
IkedaOhtsubo_&_Brune_2009 2009 Microbe Microbe n Mutualist Ecto vertical vertical resident 11 11 1 11 1.00 1.00 11 1 1000 0.00100 TreeMap
Jackson_&_Charleston_1994 1994 Vert Microbe n Parasite Endo horizontal contact resident 10 10 8 10 1.00 1.00 10 1 100 0.19000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Microbe n Parasite Endo horizontal bodily fluid resident 10 10 7 10 1.00 1.00 10 1 100 0.01000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Microbe n Parasite Endo horizontal contact resident 11 11 7 12 1.00 1.00 12 1 100 0.05000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Microbe n Parasite Endo horizontal bodily fluid resident 13 13 9 15 1.00 1.00 15 1 100 0.18000 TreeMap
Jackson_&_Charleston_1994 1994 Vert Microbe n Parasite Endo horizontal contact resident 14 14 7 17 1.00 1.00 17 1 100 0.01000 TreeMap
Jeong_et_al_1999 1999 Plant Microbe n Mutualist Endo horizontal vector resident 12 12 12 19 1.06 1.00 18 1 1000 0.23000 TreeMap
Johnson_et_al_2002 2002 Vert Invert y Parasite Ecto both contact resident 25 25 23 25 1.32 1.42 19 19 1000 0.23000 TreeMap
Johnson_et_al_2003 2003 Vert Invert y Parasite Ecto both contact resident 28 28 15 31 1.48 1.33 21 1 100 0.03000 TreeMap
Johnson_et_al_2006 2006 Vert Invert y Parasite Ecto both contact resident 10 10 NA 11 1.00 1.00 11 11 1000 0.40200 TreeMap
Jousselin_et_al_2008 2009 Plant Invert y Mutualist Endo horizontal autonomous resident 15 15 1 15 1.07 1.07 14 6 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Invert y Parasite Endo horizontal autonomous resident 13 13 1 14 1.00 1.00 14 1 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Invert y Parasite Endo horizontal autonomous resident 13 13 1 13 1.00 1.00 13 1 10000 0.01000 TreeMap
Jousselin_et_al_2008 2009 Plant Invert y Parasite Endo horizontal autonomous resident 16 16 1 18 1.06 1.06 17 2 10000 0.01000 TreeMap
Jousselin_et_al_2009 2009 Invert Microbe n Mutualist Endo vertical vertical resident 55 22 1 22 1.00 1.00 22 1 10000 0.00100 TreeMap
Kawaida_et_al_2013 2013 Invert Plant y Mutualist Endo vertical vertical resident 6 6 1 6 1.00 1.00 6 1 10000 0.00350 TreeMap
Kawakita_et_al_2004 2004 Plant Invert y Mutualist Ecto horizontal autonomous visitor 18 18 1 18 1.00 1.00 18 1 999 0.01900 TreeMap
Kelley_&_Farrell_1998 1998 Plant Invert y Parasite Endo horizontal autonomous resident 41 41 1 89 6.85 1.92 13 1 100 0.28000 TreeMap
Kikuchi_et_al_2009 2009 Invert Microbe n Mutualist Endo vertical vertical resident 14 14 5 14 1.00 1.00 14 1 1000 0.00100 TreeMap
Lanterbecq_et_al_2010 2010 Invert Invert y Parasite Endo/Ecto horizontal contact resident 16 16 12 16 1.00 1.00 16 5 5000 0.04000 TreeMap
Light_&_Hafner_2008 2008 Vert Invert y Parasite Ecto both contact resident 44 21 4 21 1.00 1.00 21 1 1000 0.00100 TreeMap
LimFong_et_al_2008 2008 Invert Microbe n Mutualist Endo vertical vertical resident 5 5 1 5 1.00 1.00 5 2 1000 0.11000 TreeMap
Liu_et_al_2013 2013 Invert Microbe n Mutualist Endo vertical vertical resident 37 37 1 37 1.00 1.00 37 1 1000 0.00100 TreeMap
Liu_et_al_2014 2014 Invert Microbe n Mutualist Endo vertical vertical resident 27 27 3 29 1.00 1.00 29 1 1000 0.01000 TreeMap
LopezVaamonde_et_al_2001 2001 Invert Invert y Parasite Endo horizontal autonomous resident 15 15 1 15 1.00 1.00 15 1 1000 0.00100 TreeMap
LopezVaamonde_et_al_2003 2003 Plant Invert y Parasite Endo horizontal autonomous resident 33 33 33 77 1.00 1.00 77 1 1000 0.21300 TreeMap
LopezVaamonde_et_al_2005 2005 Invert Invert y Parasite Endo horizontal autonomous resident 28 28 1 35 2.33 1.33 15 1 1000 0.24800 TreeMap
Martin_et_al_1999 1999 Vert Microbe n Parasite Endo horizontal body fluid resident 38 38 38 48 1.00 1.00 48 1 1000 0.00100 TreeMap
Martin_et_al_2003 2003 Vert Microbe n Parasite Endo horizontal body fluid resident 14 14 14 16 1.00 1.00 16 1 100 0.01000 TreeMap
Martin_et_al_2003 2003 Vert Microbe n Parasite Endo horizontal body fluid resident 9 9 9 9 1.00 1.00 9 1 100 0.05000 TreeMap
Martin_et_al_2003 2003 Vert Microbe n Parasite Endo horizontal body fluid resident 17 17 17 23 1.00 1.00 23 1 100 0.21000 TreeMap
Mazzon_et_al_2010 2010 Invert Microbe n Mutualist Endo vertical vertical resident 17 17 10 17 1.06 1.13 16 3 1000 0.00100 TreeMap
Morelli_&_Spicer_2007 2007 Vert Invert y Parasite Ecto both contact resident 6 6 6 6 1.00 1.00 6 1 10000 0.00950 TreeMap
Muniz_et_al_2013 2013 Vert Microbe n Parasite Endo horizontal body fluid resident 17 17 11 17 1.00 1.00 17 1 10000 0.00001 TreeMap
Musser_et_al_2010 2010 Vert Invert y Parasite Ecto both contact resident 6 6 1 6 1.00 1.00 6 6 100 0.30000 TreeMap
Pagan_et_al_2010 2010 Plant Microbe n Parasite Endo horizontal contact resident 10 10 10 13 1.00 1.00 13 1 1000 0.24000 TreeMap
Page_1996 1996 Vert Invert y Parasite Ecto both contact resident 15 15 6 17 1.00 1.00 17 2 1000 0.00100 TreeMap
Page_et_al_1998 1998 Vert Invert y Parasite Ecto both contact resident 7 7 1 8 1.00 1.00 8 1 100 0.01000 TreeMap
Page_et_al_2004 2004 Vert Invert y Parasite Ecto both contact resident 12 12 4 12 1.00 1.00 12 1 1000 0.00100 TreeMap
Page_et_al_2004 2004 Vert Invert y Parasite Ecto both contact resident 11 11 5 13 1.00 1.00 13 4 100 0.25000 TreeMap
Page_et_al_2004 2004 Vert Invert y Parasite Ecto both contact resident 13 13 5 14 1.00 1.00 14 1 100 0.46000 TreeMap
Page_et_al_2004 2004 Vert Invert y Parasite Ecto both contact resident 9 9 3 9 1.00 1.00 9 1 100 0.36000 TreeMap
Paterson_&_Poulin_1999 1999 Vert Invert y Parasite Ecto horizontal autonomous resident 8 8 8 12 1.20 2.20 10 1 100 0.01000 TreeMap
Paterson_et_al_2000 2000 Vert Invert y Parasite Ecto both contact resident 11 11 5 14 1.00 1.00 14 5 100 0.01000 TreeMap
Percy_et_al_2004 2004 Plant Invert y Parasite Ecto both autonomous resident 35 35 8 56 1.22 1.09 46 4 1000 0.00500 TreeMap
PerezLosada_et_al_2006 2006 Vert Microbe n Parasite Endo horizontal NA resident 9 9 9 11 1.00 1.00 11 1 100 0.01000 TreeMap
Perlman_et_al_2003 2003 Invert Invert y Parasite Endo horizontal autonomous resident 16 16 1 17 1.89 1.33 9 1 1000 0.14000 TreeMap
Quek_et_al_2004 2004 Plant Invert y Mutualist Ecto horizontal autonomous resident 9 9 1 9 1.00 1.00 6 1 1000 1.00000 TreeMap
Ramsden_et_al_2008 2008 Vert Microbe n Parasite Endo horizontal contact resident 33 33 20 38 1.00 1.00 38 1 1000 1.00000 TreeMap
Reed_et_al_2007 2007 Vert Invert y Parasite Ecto horizontal contact resident 4 4 4 6 1.20 1.00 5 4 1000 0.05000 TreeMap
Refregier_et_al_2008 2008 Plant Microbe y Parasite Endo horizontal vector resident 18 18 7 20 1.25 1.25 16 1 3000 0.50000 TreeMap
Riess_et_al_2018 2018 Plant Microbe Y Parasite Endo horizontal autonomous resident 11 11 5 11 1.00 1.00 11 2 1000 0.33500 TreeMap
Shoemaker_et_al_2002 2002 Invert Microbe n Mutualist Endo both NA resident 20 20 7 23 1.00 1.00 23 1 100 0.47000 TreeMap
Simkova_et_al_2013 2013 Vert Invert y Parasite Ecto horizontal autonomous resident 5 5 1 21 1.00 1.00 21 1 999 0.04500 TreeMap
Six_&_Paine_1999 1999 Microbe Invert y Mutualist Ecto horizontal vector resident 6 6 1 6 1.00 1.00 6 3 1000 0.03100 TreeMap
Skerikova_et_al_2001 2001 Vert Invert y Parasite Endo horizontal trophic resident 7 7 7 7 1.00 1.00 7 1 10000 0.40000 TreeMap
Smith_et_al_2008b 2008 Vert Invert y Parasite Ecto both contact resident 20 20 3 20 1.00 1.00 20 14 100 0.05000 TreeMap
Sorenson_et_al_2004 2004 Vert Vert y Parasite Ecto horizontal autonomous resident 33 33 10 34 1.62 1.43 21 1 100 0.15000 TreeMap
Subbotin_et_al_2004 2004 Plant Invert y Parasite Endo horizontal autonomous resident 16 16 16 21 1.00 1.00 21 4 1000 0.00100 TreeMap
Switzer_et_al_2005 2005 Vert Microbe n Parasite Endo horizontal body fluid resident 46 46 17 51 1.00 1.00 51 1 10000 0.00700 TreeMap
Urban_&_Cryan_2012 2012 Invert Microbe n Mutualist Endo vertical autonomous resident 40 40 38 40 1.00 1.00 40 1 1000 0.00100 TreeMap
Urban_&_Cryan_2012 2012 Invert Microbe n Mutualist Endo vertical autonomous resident 30 30 29 30 1.00 1.00 30 1 1000 0.00100 TreeMap
Vanhove_et_al_2015 2015 Vert Invert y Parasite Endo horizontal autonomous resident 19 19 10 28 1.00 1.00 28 1 10000 0.04210 TreeMap
Weckstein_2004 2004 Vert Invert y Parasite Ecto both contact resident 11 11 1 11 2.20 1.80 5 1 10000 0.89000 TreeMap
Weiblen_&_Bush_2002 2002 Plant Invert y Mutualist Endo horizontal autonomous resident 19 19 1 19 1.00 1.00 19 1 10000 0.01950 TreeMap
Weiblen_&_Bush_2002 2002 Plant Invert y Parasite Endo horizontal autonomous resident 12 12 1 18 1.00 1.00 18 1 10000 0.12150 TreeMap
Wu_et_al_2008 2008 Plant Microbe n Parasite Endo horizontal vector resident 8 8 8 10 1.00 1.00 10 1 100 0.01000 TreeMap
Xu_et_al_2017 2017 Invert Microbe n Mutualist Endo vertical vertical resident 20 20 8 20 1.00 1.00 20 1 1000 0.00100 TreeMap
Yan_et_al_2011 2011 Vert Microbe n Parasite Endo horizontal contact resident 8 8 8 15 1.00 1.00 15 1 999 0.98900 TreeMap

A. authors: The authors of the study and the date (citation form).

B. year: The year of publication of the study.

C. host_tax_broad: Separation of the host group according to broader taxonomic units (e.g. vertebrate, invertebrate, microbe, plant).

D. symbiont_tax_broad: Separation of the symbiont group according to broader taxonomic units (e.g. vertebrate, invertebrate, microbe, plant).

E. symbiont_euk*: Whether the symbiont is eukaryotic (state =‘yes’), or prokaryotic (state=‘no’).

F. symbiosis: The type of symbiont (e.g. parasite or mutualist). For this we followed the definition used by the authors of the study.

G. endo_or_ecto: Whether the symbiont lives outside the host (i.e. is an ectosymbiont), or inside the host (i.e. is an endosymbiont).

H. mode_of_transmission_broad: Whether the symbiont is transmitted vertically, horizontally, or both. For this, we followed the route of transmission specified by the authors of the study.

I. mode_of_transmission_fine*: A finer-scale description of the mode of transmission of the symbiont (e.g. contact, vector, bodily fluid, vertical, trophic).

J. Visiting_symbiont?* Whether the symbiont is resident on the host (resident), or makes visits to the host or hosts (visitor).

K. host_tips_linked: The number of individual host taxa included in the cophylogenetic analysis.

L. host_tips_linked_corrected The same measure as for column K, ‘host_tips_linked,’ but reduced to only include one member of each host species. This is included because some authors include multiple individuals of the same host species. Without correction, this artificially increases the apparent number of host species included in the study.

M. host_genera: A count of the number of host genera included in the cophylogenetic analysis.

N. total_host_symbiont_links The total number of links between host and symbiont taxa recorded in a study. If all symbionts were strict specialists, this would equal the number of symbionts included in the study. However, because symbionts are often associated with more than one host, this value is often higher than the total number of symbionts included in the study.

O. host_range_link_ratio: An estimation of symbiont host specificity, calculated by dividing the total number of links between hosts and symbionts (i.e. ‘total_host_symbiont_links,’ column N), by the total number of symbionts included in the study (i.e. ‘symbiont_tips_linked,’ column Q).

P. host_range_taxonomic_breadth: An alternative estimation of symbiont host specificity, calculated by first summing the number of host taxonomic ranks linked to each symbiont (i.e. single host species = 1, multiple host species in the same genus = 2, multiple host genera = 3, multiple host families = 4, multiple host orders = 5), and dividing by the total number of symbionts included in the study (i.e. ‘symbiont_tips_linked,’ column Q).

Q. symbiont_tips_linked The number of individual symbiont taxa included in the cophylogenetic analysis.

R. symbiont_genera: A count of the number of symbiont genera included in the cophylogenetic analysis.

S. no_randomizations: The number of phylogenetic randomizations performed during the cophylogenetic analysis.

T. p_value: The p-value reported for the cophylogenetic analysis, representing the likelihood that host and symbiont phylogenies display cospeciation.

U. method: Whether TreeMap or ParaFit was used to obtain the reported p value.

Table of sample sizes

Below we present our sample sizes for the two separate methods: TreeMap (Page 1994) and ParaFit (Legendre et al. 2002) (and combined), in terms of effect sizes, papers, and different levels of categorical variables (factors).

# selecting out variables, which we used for our analysis
dat <- full_data %>% select(-symbiont_euk, -mode_of_transmission_fine, -`Visiting_symbiont?`)
pair <- full_pair %>% select(-symbiont_euk, -mode_of_transmission_fine, -`Visiting_symbiont?`)

# making a table of sample sizes for different variables
dat %>% group_by(method) %>% 
  summarise(
    `Effect sizes (analyses)` = n(),
    Studies = n(), 
    Papers = n_distinct(authors),
    `Vertebrate hosts` = sum(host_tax_broad == "Vert", na.rm = T), # na.rm is important when NA exists
    `Invertebrate hosts` = sum(host_tax_broad == "Invert", na.rm = T),
    `Plant hosts`  = sum(host_tax_broad == "Plant", na.rm = T),
    `Microbe hosts` = sum(host_tax_broad == "Microbe", na.rm = T),
    `Vertebrate symbionts` = sum(symbiont_tax_broad  == "Vert", na.rm = T),
    `Invertebrate symbionts` = sum(symbiont_tax_broad  == "Invert", na.rm = T),
    `Plant symbionts`  = sum(symbiont_tax_broad  == "Plant", na.rm = T),
    `Microbe symbionts` = sum(symbiont_tax_broad  == "Microbe", na.rm = T),
    `Parastic relationships` = sum(symbiosis == "Parasite", na.rm = T),
    `Mutualistic relatioships` = sum(symbiosis == "Mutualist", na.rm = T),
    `Ecto-symbionts` = sum(endo_or_ecto  == "Ecto", na.rm = T),
    `Endo-symbionts` = sum(endo_or_ecto == "Endo", na.rm = T),
    `Ecto/endo-symbionts` = sum(endo_or_ecto == "Endo/Ecto", na.rm = T),
    `Horizontal transmission` = sum(mode_of_transmission_broad  == "horizontal", na.rm = T),
    `Vertical transmission` = sum(mode_of_transmission_broad == "vertical", na.rm = T),
    `Horizontal/vertical-transmission` = sum(mode_of_transmission_broad == "both", na.rm = T)
  ) -> n_table1

# transposing the table and creating that table and adding a correct number of the papers for `Combined`
n_authors <- n_distinct(dat$authors) # the total number of papers
dat$studies <- paste0(dat$authors, dat$host_tax_fine, dat$symbiont_tax_fine, dat$total_host_symbioint_links) # the number of analyses (studies)
n_studies <- n_distinct(dat$studies)
n_table2 <-t(n_table1[,-1])
colnames(n_table2) <- n_table1$method
n_table2 %>% as_tibble(rownames = "Number") %>% 
  mutate(Combined = Parafit + TreeMap, Combined = replace(Combined, c(2,3), c(n_studies, n_authors))) %>%  
  rename("Number of" = "Number", "ParaFit (n)" = "Parafit", "TreeMap (n)" = "TreeMap",  "Combined (n)" = "Combined") %>% 
  kable() %>% kable_styling("striped", position = "left") %>%
  scroll_box(width = "100%", height = "250px")
Number of ParaFit (n) TreeMap (n) Combined (n)
Effect sizes (analyses) 140 93 233
Studies 140 93 211
Papers 118 78 180
Vertebrate hosts 60 51 111
Invertebrate hosts 39 20 59
Plant hosts 31 18 49
Microbe hosts 10 4 14
Vertebrate symbionts 1 1 2
Invertebrate symbionts 62 49 111
Plant symbionts 3 1 4
Microbe symbionts 74 42 116
Parastic relationships 91 70 161
Mutualistic relatioships 48 23 71
Ecto-symbionts 41 34 75
Endo-symbionts 97 58 155
Ecto/endo-symbionts 2 1 3
Horizontal transmission 84 53 137
Vertical transmission 28 15 43
Horizontal/vertical-transmission 23 25 48
  #pander(split.cell = 40, split.table = Inf) # not as nice as kable

Note that the numbers of studies and papers does not add up (TreeMap + ParaFit \(\neq\) Combined), because 22 analyses and 16 papers used both the TreeMap and ParaFit methods (the term “papers” here is our variable authors)

Missing data patterns

Below, we present the number of instances of missing data (cells) for all variables used in our meta-analysis.

# summaring missingness in our dataset
# funs(sum(is.na(.))) needs to be in funs as is.na has "." = each column
dat %>% summarise_all(~sum(is.na(.))) %>% # map(~sum(is.na(.)) # this is an alterantive way 
  t() %>% as_tibble(rownames = "Variable") %>% 
  rename("Number of missing data (n)" = "V1") %>% 
  #pander(split.cell = 40, split.table = Inf)
  kable() %>% kable_styling("striped", position = "left") %>%
  scroll_box(width = "60%", height = "250px")
Variable Number of missing data (n)
authors 0
year 0
host_tax_broad 0
symbiont_tax_broad 0
symbiosis 1
endo_or_ecto 0
mode_of_transmission_broad 5
host_tips_linked 0
host_tips_linked_corrected 0
host_genera 6
total_host_symbioint_links 3
host_range_link_ratio 3
host_range_taxonomic_breadth 7
symbiont_tips_linked 0
symbiont_genera 9
no_randomizations 0
p_value 0
method 0
studies 0
# an alternative method using the mi package
#missing_data_tbl <- missing_data.frame(as.data.frame(data))
#show(missing_data_tbl) 

Appendix S2: Meta-analysis

Calculating effect sizes

We created our effect size (correlation coefficient r and its Fisher’s z transformation Zr) from p values and associated sample sizes (Rosenthal & Rubin 2003). We used half of the“effective sample size” for each effect size (an indicator of congruence):

\[ N_{effective} = \frac{4n_{h}n_{s}} {n_{h} + n_{s}}, \] where \(n_h\) and \(n_s\) are sample size for hosts and symbionts (in our case: host_tips_linked_corrected and symbiont_tips_linked). When \(n = n_h = n_s\), \(N_{effective}\) simplifies to \(2n\). We used \(N_{effective}/2\), which we called the number of “effective pairs” (\(N_{ep}\)) as our sample size.

Also, we created a column with a unique ID for each observation (i.e. an observation level random effect), termed observation, which is required for the rma.mv function in metafor (Viechtbauer 2010).

dat %<>% # getting sample size & observation level random effect
mutate(., sample_size = 2 * (host_tips_linked_corrected * symbiont_tips_linked)/(host_tips_linked_corrected + 
    symbiont_tips_linked), observation = factor(1:nrow(.)))  #, signficance = if_else(p_value <= 0.05, 'y', 'n') ) 

# making p = 1 to p = (no_randomization - 1)/no_randomization as p = 1 produces t
# value = Inf
dat$p_value <- ifelse(dat$p_value != 1, dat$p_value, (dat$no_randomizations - 1)/dat$no_randomizations)

# calculating effect size
dat %<>% p_to_Zr(p_value, sample_size)

# getting sample size for spp sum(dat$sample_size[match(unique(dat$studies),
# dat$studies)])

# getting effect sizes for pair data
pair %<>% # getting sample size & observation level random effect
mutate(., sample_size = 2 * (host_tips_linked_corrected * symbiont_tips_linked)/(host_tips_linked_corrected + 
    symbiont_tips_linked), observation = factor(1:nrow(.)))

# making p = 1 to p = (no_randomization - 1)/no_randomization as p = 1 produces t
# value = Inf
pair$p_value_tree <- ifelse(pair$p_value_tree == 1, 0.999, pair$p_value_tree)
# calculating effect size
pair %<>% p_to_Zr(p_value_para, sample_size) %>% rename(rval_para = rval, Zr_para = Zr, 
    VZr_para = VZr) %>% p_to_Zr(p_value_tree, sample_size) %>% rename(rval_tree = rval, 
    Zr_tree = Zr, VZr_tree = VZr)

Correlating two methods on the same cophylogenetic data

In 16 studies, authors used both ParaFit and TreeMap on the same cophylogeny dataset, but in some of these studies, they used different numbers of randomization between the two methods. Among these 16, 11 studies used ParaFit and TreeMap with the same or similar number of randomization (e.g., 999 and 1,000). We here correlated effect sizes (Zr) between these two methods. In the following analyses, we assume the p-value based effect size, Zr~equivalent (or just Zr) is equivalent for both methods. In such a case, we would require a tight correlation between the method.

# plotting correlations but not displayed A)
cor_1 <- round(with(pair, cor(Zr_para, Zr_tree)), 3)
cor_t1 <- with(pair, cor.test(Zr_para, Zr_tree))

all_plot <- ggplot(pair, aes(Zr_para, Zr_tree)) + geom_point() + geom_smooth(method = "lm") + 
    labs(x = "Zr (ParaFit)", y = "Zr (TreeMap)") + annotate("text", x = 1, y = -1, 
    label = paste("r = ", cor_1))

# B)
cor_2 <- round(with(pair[pair$match == "y", ], cor(Zr_para, Zr_tree)), 3)
cor_t2 <- with(pair[pair$match == "y", ], cor.test(Zr_para, Zr_tree))

part_plot <- ggplot(pair[pair$match == "y", ], aes(Zr_para, Zr_tree)) + geom_point() + 
    geom_smooth(method = "lm") + labs(x = "Zr (ParaFit)", y = "Zr (TreeMap)") + annotate("text", 
    x = 1, y = -1, label = paste("r = ", cor_2))

comb_plot <- all_plot + part_plot + plot_annotation(tag_levels = "A", tag_suffix = ")")
# comb_plot

There are strong and significant correlations in effect sizes (Zr) between ParaFit and TreeMap (for all the 16 studies, r = 0.737, t = 4.075, df = 14, p = 0.0011, and for the 11 perfectly matching studies, r = 0.781, t = 3.757, df = 9, p = 0.0045). Therefore, we have made an assumption that effect sizes based on p values from these two methods can be equated in our analyses below.

Meta-analytic model: testing Fahrenholz’s rule

First, we checked what random effects should be put into the main model. To do this we fitted two random effects, authors (i.e. study IDs) and observation; the former term was added to account for non-independence of effect sizes originating from the same papers (i.e., authors).

# 2 random effects & model AIC note that probably only base stuff works outside
# of main chunck so need to create AIC here
ma_test1 <- rma.mv(yi = Zr, V = VZr, random = list(~1 | authors, ~1 | observation), 
    data = dat)
aic1 <- AIC(ma_test1)

# 1 random effect & model AIC
ma_test2 <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, data = dat)
aic2 <- AIC(ma_test2)

The model (ma_test1), which included both random factors, had a larger AIC value (279.99) than the model with only one random effect (277.99) . This is because observation hardly accounted for any variance (< 0.0001) compared to authors (0.0811). Therefore, we only included authors as our random factor in subsequent analyses.

We ran intercept models (meta-analyses) with 3 different datasets (ParaFit, TreeMap and both combined; see the explanation of method above). Also, we note that we used adjustments for test statistics and confidence intervals (test = "t"), which is similar to (but not the same as) those proposed by Knapp and Hartung (Knapp & Hartung 2003); probably this approach is more conservative.

Running Multilevel Meta-analytic models with 3 datasets

# think about making this into a tibble meta-analysis with Parafit
ma_parafit <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, test = "t", subset = which(method == 
    "TreeMap"), data = dat)

# meta-analysis with TreeMap
ma_treemap <- rma.mv(yi = Zr, V = VZr, random = ~1 | authors, test = "t", subset = which(method == 
    "Parafit"), data = dat)

# meta-analysis with all the data combined
ma_all <- rma.mv(yi = Zr, V = VZr, test = "t", random = ~1 | authors, data = dat)

Table S2.1

Overall effects (meta-analytic means) and 95% confidence intervals (CIs) both in Zr and r, and variance components (V) and heterogeneity, I2 (I2) (Higgins et al. 2003) from the metafor model using the 3 datasets (ParaFit, TreeMap and both combined, or All). Note that in these models, I2[total] = I2[authors] (see (Nakagawa & Santos 2012; Senior et al. 2016)), as we only have one random factor.

# getting I2 for the models could use map()
i2_treemap <- I2(ma_treemap)
i2_parafit <- I2(ma_parafit)
i2_all <- I2(ma_all)
# creating a table
tibble(Dataset = c("Parafit (Zr)", "TreeMap (Zr)", "All (Zr)", "Parafit (r)", "TreeMap (r)", 
    "All (r)"), `Overall mean` = c(ma_parafit$b, ma_treemap$b, ma_all$b, tanh(ma_parafit$b), 
    tanh(ma_treemap$b), tanh(ma_all$b)), `Lower CI [0.025]` = c(ma_parafit$ci.lb, 
    ma_treemap$ci.lb, ma_all$ci.lb, tanh(ma_parafit$ci.lb), tanh(ma_treemap$ci.lb), 
    tanh(ma_all$ci.lb)), `Upper C  [0.975]` = c(ma_parafit$ci.ub, ma_treemap$ci.ub, 
    ma_all$ci.ub, tanh(ma_parafit$ci.ub), tanh(ma_treemap$ci.ub), tanh(ma_all$ci.ub)), 
    `V[authors]` = c(ma_parafit$sigma2, ma_treemap$sigma2, ma_all$sigma2, rep(NA, 
        3)), `I2[total]` = c(i2_parafit[1], i2_treemap[1], i2_all[1], rep(NA, 3))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Dataset Overall mean Lower CI [0.025] Upper C [0.975] V[authors] I2[total]
Parafit (Zr) 0.518 0.425 0.610 0.084 0.526
TreeMap (Zr) 0.544 0.477 0.610 0.072 0.627
All (Zr) 0.536 0.479 0.593 0.081 0.612
Parafit (r) 0.476 0.401 0.544 NA NA
TreeMap (r) 0.496 0.444 0.544 NA NA
All (r) 0.490 0.446 0.532 NA NA

These models all gave consistent results including heterogeneity. Given these results, we proceeded with only analyzing the whole dataset (All) from here on.

Figure 3a

# https://stackoverflow.com/questions/41919023/ggplot-adding-image-on-top-right-in-two-plots-with-different-scales
# how to add png files to the figure (above) reading image
image_mutualism <- readPNG(here("images/mutualism_transparentbg.png"))
image_parasitism <- readPNG(here("images/parasitism_transparentbg.png"))

# creating a table of results
pred_ma <- get_pred(ma_all)
effect_ma <- get_est(ma_all) %>% left_join(pred_ma)

# creating An orchard plot
fig_ma <- ggplot(data = effect_ma, aes(x = tanh(estimate), y = "Overall mean")) + 
    scale_x_continuous(limits = c(-1, 1), breaks = seq(-1, 1, by = 0.2)) + geom_quasirandom(data = dat, 
    aes(x = tanh(Zr), y = "Overall mean", size = (1/VZr) + 3), groupOnX = FALSE, 
    alpha = 0.2) + # precition interval (PI)
geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)), height = 0, show.legend = F, 
    size = 0.5, alpha = 0.6) + # CI
geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)), height = 0, show.legend = F, 
    size = 1.2) + 
geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) + # creating dots and different size (bee-swarm and bubbles)
geom_point(size = 3, shape = 21, fill = "black") + annotate("text", x = 0.93, y = 1.15, 
    label = paste("italic(k)==", length(dat$Zr)), parse = TRUE, hjust = "left", size = 3.5) + 
    labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), 
        " (# of species pair)"))) + theme_bw() + theme(legend.position = c(0, 1), 
    legend.justification = c(0, 1)) + theme(legend.direction = "horizontal") + # theme(legend.background = element_rect(fill = 'white', colour = 'black')) +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90)) + annotation_custom(rasterGrob(image_mutualism), 
    xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + annotation_custom(rasterGrob(image_parasitism), 
    xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2)
# ggsave(plot = fig_ma, filename = 'fig_2a.pdf', height = 2, width = 8) ggploty 0
# does not work (Error in unique.default(x) : unimplemented type 'expression' in
# 'HashTableSetup')
fig_ma

# for Fig 3

a <- ggplot(data = effect_ma, aes(x = tanh(estimate), y = "Overall mean")) + scale_x_continuous(limits = c(-1, 
    1), breaks = seq(-1, 1, by = 0.2)) + geom_quasirandom(data = dat, aes(x = tanh(Zr), 
    y = "Overall mean", size = (1/VZr) + 3), groupOnX = FALSE, alpha = 0.2) + # precition interval (PI)
geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)), height = 0, show.legend = F, 
    size = 0.5, alpha = 0.6) + # CI
geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)), height = 0, show.legend = F, 
    size = 1.2) + 
geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) + # creating dots and different size (bee-swarm and bubbles)
geom_point(size = 3, shape = 21, fill = "black") + annotate("text", x = 0.93, y = 1.15, 
    label = paste("italic(k)==", length(dat$Zr)), parse = TRUE, hjust = "left", size = 3.5) + 
    labs(x = "", y = "", size = expression(paste(italic(n), " (# of species pairs)")), 
        tag = "a") + theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 
    1)) + theme(legend.direction = "horizontal") + # theme(legend.background = element_rect(fill = 'white', colour = 'black')) +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90)) + annotation_custom(rasterGrob(image_mutualism), 
    xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + annotation_custom(rasterGrob(image_parasitism), 
    xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2)

Figure 3a: An orchard plot showing the meta-analytic mean (mean effect size) with its 95% confidence interval (thick line) and 95% prediction interval (thin line), with observed effect sizes based on various sample sizes.

Appendix S3: Meta-regression

We ran a univariate meta-regression model for each of the following moderators: 1) symbiosis, 2) host_tax_broad, 3) symbiont_tax_broad, 4) host_range_link_ratio, 5) host_range_taxonomic_breadth, 6) mode_of_transmission_broad, and 7) endo_or_ecto. The results from these models are presented in the main text.

In addition to these, we ran three more univariate models: 1) host_tax_symbiosis (equivalent to the interaction term between symbiosis and host_tax_symbiosis; symbiosis*host_tax_symbiosis), 2) symbiont_tax_symbiosis (symbiosis*symbiont_tax_broad), 3) host_symbiont_tax (host_tax_symbiosis*symbiont_tax_broad) and 4) symbiosis_transmission (symbiosis*mode_of_transmission_broad). These moderators are created below:

dat %<>% 
    # host_tax_broad*symbiosis (host_tax_symbiosis) 
  mutate(host_tax_symbiosis = str_c(host_tax_broad, symbiosis), 
         host_tax_symbiosis = ifelse(host_tax_symbiosis == "InvertNA", NA, host_tax_symbiosis),
         host_tax_symbiosis = factor(host_tax_symbiosis),
         # symbiont_tax_broad*symbiosis (symbiont_tax_symbiosis)     
         symbiont_tax_symbiosis = factor(str_c(symbiont_tax_broad, symbiosis)),
         # host_tax_broad*symbiont_tax_broad (host_symbiont_tax)     
         host_symbiont_tax  = factor(str_c(host_tax_broad, symbiont_tax_broad)),
         # symbiosis*mode_of_transmission_broad (symbiosis_transmission)
         symbiosis_transmission  = factor(str_c(symbiosis, mode_of_transmission_broad)),
         # whether p values were the smallest value given the number of randamization - limit_researched (Yes = 1, No = 0)
         limit_reached = if_else(abs((1/p_value) - no_randomizations) <= 1, 1, 0))

Univariate (uni-predictor) analyses

We first conducted a series of meta-regression models with each of the moderators introduced above.

The type of symbiosis: parasitism vs. mutualism

# meta-regression: mutiple intercepts
mr_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis - 1, test = "t", random = ~1 | 
    authors, data = dat)
# meta-regression: contrast
mr_symbiosis2 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis, test = "t", random = ~1 | 
    authors, data = dat)

Table S3.1

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (Nakagawa & Schielzeth 2013) (R2) from the meta-regression with symbiosis. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_symbiosis1 <- R2(mr_symbiosis1)

# getting estimates``
res_symbiosis1 <- get_est(mr_symbiosis1, mod = "symbiosis")
res_symbiosis2 <- get_est(mr_symbiosis2, mod = "symbiosis")

# creating a table
t_symbiosis <- tibble(`Fixed effect` = c(rep(as.character(res_symbiosis1$name), 2), 
    cont_gen(res_symbiosis1$name)), Unit = c(rep(c("Zr (mu)", "r (mu)"), each = 2), 
    "Zr (beta)"), Estimate = c(res_symbiosis1$estimate, tanh(res_symbiosis1$estimate), 
    res_symbiosis2$estimate[2]), `Lower CI [0.025]` = c(res_symbiosis1$lowerCL, tanh(res_symbiosis1$lowerCL), 
    res_symbiosis2$lowerCL[2]), `Upper CI  [0.975]` = c(res_symbiosis1$upperCL, tanh(res_symbiosis1$upperCL), 
    res_symbiosis2$upperCL[2]), `V[authors]` = c(mr_symbiosis1$sigma2, rep(NA, 4)), 
    R2 = c(r2_symbiosis1[1], rep(NA, 4)))
t_symbiosis %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Mutualist Zr (mu) 0.631 0.534 0.727 0.078 0.054
Parasite Zr (mu) 0.487 0.419 0.554 NA NA
Mutualist r (mu) 0.559 0.488 0.621 NA NA
Parasite r (mu) 0.451 0.396 0.503 NA NA
Mutualist-Parasite Zr (beta) -0.144 -0.260 -0.028 NA NA

Figure 3b

# adding sample size (k) for each category
k_symbiosis <- dat %>% group_by(symbiosis) %>% count()
# getting estimates and predicitons
pred_symbiosis <- get_pred(mr_symbiosis1, mod = "symbiosis") 
res_symbiosis1 <- left_join(res_symbiosis1, k_symbiosis, by =  c("name" = "symbiosis"))  %>% left_join(pred_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiosis <- ggplot(data = res_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis)), 
                   aes(x= tanh(Zr), y = symbiosis, size = ((1/VZr) + 3), colour = symbiosis), groupOnX = FALSE, alpha=0.2) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  scale_fill_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  annotate('text', x = 0.93, y = c(1.15, 2.15), label= paste("italic(k)==", res_symbiosis1$n), parse = TRUE, hjust = "left", size = 3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_mutualism), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2)

fig_symbiosis

# fig 3

b <- ggplot(data = res_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis)), 
                   aes(x= tanh(Zr), y = symbiosis, size = ((1/VZr) + 3), colour = symbiosis), groupOnX = FALSE, alpha=0.2) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  scale_fill_manual(values = c("Mutualist" = "#E69F00", "Parasite" = "#56B4E9")) +
  annotate('text', x = 0.93, y = c(1.15, 2.15), label= paste("italic(k)==", res_symbiosis1$n), parse = TRUE, hjust = "left", size = 3.5) +
  labs(x = "", y = "", tag = "b") +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_mutualism), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2)

Figure 3b: An orchard plot showing the group-wise means (the categorical variable symbiosis) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

The effect of host taxa

# reordering
dat$host_tax_broad <- factor(dat$host_tax_broad, levels = c("Microbe", "Plant", "Invert", 
    "Vert"))

# meta-regression: mutiple intercepts
mr_host_tax_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad - 1, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_host_tax_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_host_tax_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_broad, ref = "Plant"), 
    test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 3
mr_host_tax_broad4 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_broad, ref = "Invert"), 
    test = "t", random = ~1 | authors, data = dat)

Table S3.2

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with host_tax_broad. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_host_tax_broad1 <- R2(mr_host_tax_broad1)

# getting estimates
res_host_tax_broad1 <- get_est(mr_host_tax_broad1, mod = "host_tax_broad")
res_host_tax_broad2 <- get_est(mr_host_tax_broad2, mod = "host_tax_broad")
# the name bit does not work if relevel....
res_host_tax_broad3 <- get_est(mr_host_tax_broad3, mod = "host_tax_broad")
res_host_tax_broad4 <- get_est(mr_host_tax_broad4, mod = "host_tax_broad")

# creating a table
t_host_tax <- tibble(`Fixed effect` = c(rep(as.character(res_host_tax_broad1$name), 
    2), cont_gen(res_host_tax_broad1$name)), Unit = c(rep(c("Zr (mu)", "r (mu)"), 
    each = 4), rep("Zr (beta)", 6)), Estimate = c(res_host_tax_broad1$estimate, tanh(res_host_tax_broad1$estimate), 
    res_host_tax_broad2$estimate[-1], res_host_tax_broad3$estimate[-(1:2)], res_host_tax_broad4$estimate[-(1:3)]), 
    `Lower CI [0.025]` = c(res_host_tax_broad1$lowerCL, tanh(res_host_tax_broad1$lowerCL), 
        res_host_tax_broad2$lowerCL[-1], res_host_tax_broad3$lowerCL[-(1:2)], res_host_tax_broad4$lowerCL[-(1:3)]), 
    `Upper CI  [0.975]` = c(res_host_tax_broad1$upperCL, tanh(res_host_tax_broad1$upperCL), 
        res_host_tax_broad2$upperCL[-1], res_host_tax_broad3$upperCL[-(1:2)], res_host_tax_broad4$upperCL[-(1:3)]), 
    `V[authors]` = c(mr_host_tax_broad1$sigma2, rep(NA, 13)), R2 = c(r2_host_tax_broad1[1], 
        rep(NA, 13)))

t_host_tax %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left") %>% 
    scroll_box(width = "100%", height = "300px")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe Zr (mu) 0.883 0.639 1.126 0.077 0.162
Plant Zr (mu) 0.377 0.256 0.498 NA NA
Invert Zr (mu) 0.629 0.522 0.736 NA NA
Vert Zr (mu) 0.515 0.435 0.595 NA NA
Microbe r (mu) 0.708 0.564 0.810 NA NA
Plant r (mu) 0.360 0.250 0.460 NA NA
Invert r (mu) 0.557 0.479 0.627 NA NA
Vert r (mu) 0.474 0.410 0.534 NA NA
Microbe-Plant Zr (beta) -0.506 -0.778 -0.234 NA NA
Microbe-Invert Zr (beta) -0.254 -0.519 0.012 NA NA
Microbe-Vert Zr (beta) -0.367 -0.624 -0.111 NA NA
Plant-Invert Zr (beta) 0.252 0.091 0.414 NA NA
Plant-Vert Zr (beta) 0.139 -0.006 0.284 NA NA
Invert-Vert Zr (beta) -0.114 -0.244 0.017 NA NA

Figure 3c

# getting images
image_invertebrate_host <- readPNG(here("images/invertebrate_host_transparentbg.png"))
image_microbe_host <- readPNG(here("images/microbe_host_transparentbg.png"))
image_vertebrate_host <- readPNG(here("images/vertebrate_host_transparentbg.png"))
image_plant_host <- readPNG(here("images/plant_host_transparentbg.png"))

# adding sample size (k) for each category
k_host_tax_broad <- dat %>% group_by(host_tax_broad) %>% count()
# getting estimates and predicitons
pred_host_tax_broad <- get_pred(mr_host_tax_broad1, mod = "host_tax_broad") 
res_host_tax_broad1 <- left_join(res_host_tax_broad1, k_host_tax_broad, by =  c("name" = "host_tax_broad"))  %>% left_join(pred_host_tax_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_tax_broad <- ggplot(data = res_host_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_tax_broad)), 
                   aes(x= tanh(Zr), y = host_tax_broad, size = ((1/VZr) + 3), colour = host_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = 0.93, y = 1:4 + 0.15, label= paste("italic(k)==", res_host_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_plant_host), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1, xmax = -0.8, ymin = 3.6, ymax = 4.2)

fig_host_tax_broad

# fig 3c
c <- ggplot(data = res_host_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_tax_broad)), 
                   aes(x= tanh(Zr), y = host_tax_broad, size = ((1/VZr) + 3), colour = host_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = 0.93, y = 1:4 + 0.15, label= paste("italic(k)==", res_host_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = "", y = "", size = expression(paste(italic(n), " (# of species pairs)")) , tag = "c") +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_plant_host), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1, xmax = -0.8, ymin = 3.6, ymax = 4.2)

Figure 3c: An orchard plot showing the group-wise means (the categorical variable host_tax_broad) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

The effect of symbiont taxa

# reordering
dat$symbiont_tax_broad <- factor(dat$symbiont_tax_broad, levels = c("Microbe", "Plant", 
    "Invert", "Vert"))

# sizes <- factor(sizes, levels = c('small', 'medium', 'large')) sizes > [1]
# small large large small medium > Levels: small medium large meta-regression:
# mutiple intercepts
mr_symbiont_tax_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_broad - 1, 
    test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_symbiont_tax_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_broad, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_symbiont_tax_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_broad, 
    ref = "Plant"), test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 3
mr_symbiont_tax_broad4 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_broad, 
    ref = "Invert"), test = "t", random = ~1 | authors, data = dat)

Table S3.3

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with symbiont_tax_broad. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_symbiont_tax_broad1 <- R2(mr_symbiont_tax_broad1)

# getting estimates
res_symbiont_tax_broad1 <- get_est(mr_symbiont_tax_broad1, mod = "symbiont_tax_broad")
res_symbiont_tax_broad2 <- get_est(mr_symbiont_tax_broad2, mod = "symbiont_tax_broad")
res_symbiont_tax_broad3 <- get_est(mr_symbiont_tax_broad3, mod = "symbiont_tax_broad")
res_symbiont_tax_broad4 <- get_est(mr_symbiont_tax_broad4, mod = "symbiont_tax_broad")

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiont_tax_broad1$name), as.character(res_symbiont_tax_broad1$name), 
    cont_gen(res_symbiont_tax_broad1$name)), Unit = c(rep(c("Zr (mu)", "r (mu)"), 
    each = 4), rep("Zr (beta)", 6)), Estimate = c(res_symbiont_tax_broad1$estimate, 
    tanh(res_symbiont_tax_broad1$estimate), res_symbiont_tax_broad2$estimate[-1], 
    res_symbiont_tax_broad3$estimate[-(1:2)], res_symbiont_tax_broad4$estimate[-(1:3)]), 
    `Lower CI [0.025]` = c(res_symbiont_tax_broad1$lowerCL, tanh(res_symbiont_tax_broad1$lowerCL), 
        res_symbiont_tax_broad2$lowerCL[-1], res_symbiont_tax_broad3$lowerCL[-(1:2)], 
        res_symbiont_tax_broad4$lowerCL[-(1:3)]), `Upper CI  [0.975]` = c(res_symbiont_tax_broad1$upperCL, 
        tanh(res_symbiont_tax_broad1$upperCL), res_symbiont_tax_broad2$upperCL[-1], 
        res_symbiont_tax_broad3$upperCL[-(1:2)], res_symbiont_tax_broad4$upperCL[-(1:3)]), 
    `V[authors]` = c(mr_symbiont_tax_broad1$sigma2, rep(NA, 13)), R2 = c(r2_symbiont_tax_broad1[1], 
        rep(NA, 13))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe Zr (mu) 0.546 0.467 0.624 0.081 0.078
Plant Zr (mu) 1.140 0.671 1.609 NA NA
Invert Zr (mu) 0.507 0.423 0.591 NA NA
Vert Zr (mu) 0.440 -0.191 1.071 NA NA
Microbe r (mu) 0.497 0.436 0.554 NA NA
Plant r (mu) 0.814 0.585 0.923 NA NA
Invert r (mu) 0.467 0.399 0.531 NA NA
Vert r (mu) 0.414 -0.189 0.790 NA NA
Microbe-Plant Zr (beta) 0.594 0.118 1.070 NA NA
Microbe-Invert Zr (beta) -0.039 -0.154 0.076 NA NA
Microbe-Vert Zr (beta) -0.106 -0.742 0.531 NA NA
Plant-Invert Zr (beta) -0.633 -1.110 -0.156 NA NA
Plant-Vert Zr (beta) -0.700 -1.487 0.087 NA NA
Invert-Vert Zr (beta) -0.067 -0.704 0.570 NA NA

Figure 3d

# getting images
image_invertebrate_parasite <- readPNG(here("images/invertebrate_parasite_transparentbg.png"))
image_microbe_parasite <- readPNG(here("images/microbe_parasite_transparentbg.png"))
image_vertebrate_parasite <- readPNG(here("images/vertebrate_parasite_transparentbg.png"))
image_plant_parasite <- readPNG(here("images/plant_parasite_transparentbg.png"))

# adding sample size (k) for each category
k_symbiont_tax_broad <- dat %>% group_by(symbiont_tax_broad) %>% count()
# getting estimates and predicitons
pred_symbiont_tax_broad <- get_pred(mr_symbiont_tax_broad1, mod = "symbiont_tax_broad") 
res_symbiont_tax_broad1 <- left_join(res_symbiont_tax_broad1, k_symbiont_tax_broad, by =  c("name" = "symbiont_tax_broad"))  %>% left_join(pred_symbiont_tax_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiont_tax_broad <- ggplot(data = res_symbiont_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiont_tax_broad)), 
                   aes(x= tanh(Zr), y = symbiont_tax_broad, size = ((1/VZr) + 3), colour = symbiont_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00" )) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = 0.93, y = 1:4 + 0.15, label= paste("italic(k)==", res_symbiont_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertebrate_parasite), xmin = -1, xmax = -0.8, ymin = 3.6, ymax = 4.2)

fig_symbiont_tax_broad

# fig 3d
d <- ggplot(data = res_symbiont_tax_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiont_tax_broad)), 
                   aes(x= tanh(Zr), y = symbiont_tax_broad, size = ((1/VZr) + 3), colour = symbiont_tax_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00" )) +
  scale_fill_manual(values = c("Microbe" = "#009E73",  "Plant" = "#F0E422",  "Invert"= "#0072B2",  "Vert" = "#D55E00")) +
  scale_y_discrete(labels = c("Microbe" = "Microbe",  "Plant" = "Plant",  "Invert"= "Invertebrate",  "Vert" = "Vertebrate")) +
  annotate('text', x = 0.93, y = 1:4 + 0.15, label= paste("italic(k)==", res_symbiont_tax_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")), tag = "d") +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -1, xmax = -0.8, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertebrate_parasite), xmin = -1, xmax = -0.8, ymin = 3.6, ymax = 4.2)

Figure 3d: An orchard plot showing the group-wise means (the categorical variable symbiont_tax_broad) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

Testing specialization 1: host range

# meta-regression
mr_host_range_link_ratio <- rma.mv(yi = Zr, V = VZr, mods = ~log(host_range_link_ratio), 
    random = ~1 | authors, data = dat)

Table S3.4

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with log(host_range_link_ratio). Note that mu shows the overall while beta represents a slope in the Unit column.

# getting marginal R2
r2_host_range_link_ratio <- R2(mr_host_range_link_ratio)

# getting estimates: name does not work for slopes
res_host_range_link_ratio <- get_est(mr_host_range_link_ratio, mod = "log(host_range_link_ratio)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "Intercept", "log(host_range_link_ratio)"), 
    Unit = c(rep(c("Zr (mu)", "r (mu)"), 1), rep("Zr (beta)", 1)), Estimate = c(res_host_range_link_ratio$estimate[1], 
        tanh(res_host_range_link_ratio$estimate[1]), res_host_range_link_ratio$estimate[2]), 
    `Lower CI [0.025]` = c(res_host_range_link_ratio$lowerCL[1], tanh(res_host_range_link_ratio$lowerCL[1]), 
        res_host_range_link_ratio$lowerCL[2]), `Upper CI  [0.975]` = c(res_host_range_link_ratio$upperCL[1], 
        tanh(res_host_range_link_ratio$upperCL[1]), res_host_range_link_ratio$upperCL[2]), 
    `V[authors]` = c(mr_host_range_link_ratio$sigma2, NA, NA), R2 = c(r2_host_range_link_ratio[1], 
        NA, NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept Zr (mu) 0.549 0.484 0.614 0.083 0.002
Intercept r (mu) 0.500 0.449 0.547 NA NA
log(host_range_link_ratio) Zr (beta) -0.037 -0.187 0.114 NA NA
# newmods <- seq(-0.3, 2.2, by = 0.1)
# pred_host_range_link_ratio <-predict.rma(mr_host_range_link_ratio, newmods = newmods) 
# ribbon_dat <- tibble(newmods = newmods, ymin = pred_host_range_link_ratio$ci.lb, ymax = pred_host_range_link_ratio$ci.ub)
pred_host_range_link_ratio <-predict.rma(mr_host_range_link_ratio) 

# plotting

fig_host_range_link_ratio <-  dat %>% 
  filter(!is.na(host_range_link_ratio))  %>% # getting ride of NA values
  mutate(ymin = pred_host_range_link_ratio$ci.lb, 
         ymax = pred_host_range_link_ratio$ci.ub,
         ymin2 = pred_host_range_link_ratio$cr.lb,
         ymax2 = pred_host_range_link_ratio$cr.ub,
         pred = pred_host_range_link_ratio$pred) %>% 
  ggplot(aes(x = log(host_range_link_ratio), y = Zr, size = (1/VZr) + 3, )) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(-0.05, 2) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "ln(host range link ratio)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species pairs)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(1, 1), legend.justification = c(1, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_range_link_ratio

Figure S3.1

A bubble plot showing a predicted regression line for the continuous variable log(host_range_link_ratio), indicating 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines) with observed effect sizes based on various sample sizes.

Testing specialization 2: taxonomic breadth

# meta-regression
mr_host_range_taxonomic_breadth <- rma.mv(yi = Zr, V = VZr, mods = ~log(host_range_taxonomic_breadth), 
    random = ~1 | authors, data = dat)

Table S3.5

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with log(host_range_taxonomic_breadth). Note that mu shows the overall while beta represents a slope in the Unit column.

# getting marginal R2
r2_host_range_taxonomic_breadth <- R2(mr_host_range_taxonomic_breadth)

# getting estimates: name does not work for slopes
res_host_range_taxonomic_breadth <- get_est(mr_host_range_taxonomic_breadth, mod = "log(host_range_taxonomic_breadth)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "Intercept", "log(host_range_taxonomic_breadth)"), 
    Unit = c(rep(c("Zr (mu)", "r (mu)"), 1), rep("Zr (beta)", 1)), Estimate = c(res_host_range_taxonomic_breadth$estimate[1], 
        tanh(res_host_range_taxonomic_breadth$estimate[1]), res_host_range_taxonomic_breadth$estimate[2]), 
    `Lower CI [0.025]` = c(res_host_range_taxonomic_breadth$lowerCL[1], tanh(res_host_range_taxonomic_breadth$lowerCL[1]), 
        res_host_range_taxonomic_breadth$lowerCL[2]), `Upper CI  [0.975]` = c(res_host_range_taxonomic_breadth$upperCL[1], 
        tanh(res_host_range_taxonomic_breadth$upperCL[1]), res_host_range_taxonomic_breadth$upperCL[2]), 
    `V[authors]` = c(mr_host_range_taxonomic_breadth$sigma2, NA, NA), R2 = c(r2_host_range_taxonomic_breadth[1], 
        NA, NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept Zr (mu) 0.559 0.494 0.623 0.081 0.001
Intercept r (mu) 0.507 0.458 0.554 NA NA
log(host_range_taxonomic_breadth) Zr (beta) -0.036 -0.216 0.143 NA NA
pred_host_range_taxonomic_breadth <-predict.rma(mr_host_range_taxonomic_breadth) 

# plotting

fig_host_range_taxonomic_breadth <-  dat %>% 
  filter(!is.na(host_range_taxonomic_breadth))  %>% # getting ride of NA values
  mutate(ymin = pred_host_range_taxonomic_breadth$ci.lb, 
         ymax = pred_host_range_taxonomic_breadth$ci.ub,
         ymin2 = pred_host_range_taxonomic_breadth$cr.lb,
         ymax2 = pred_host_range_taxonomic_breadth$cr.ub,
         pred = pred_host_range_taxonomic_breadth$pred) %>% 
  ggplot(aes(x = log(host_range_taxonomic_breadth), y = Zr, size = (1/VZr) + 3, )) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(0, 1.5) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "ln(host range taxonomic breadth)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species pairs)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(1, 1), legend.justification = c(1, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fig_host_range_taxonomic_breadth

Figure S3.2

A bubble plot showing a predicted regression line for the continuous variable log(log(host_range_taxonomic_breadth), indicating 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines) with observed effect sizes based on various sample sizes.

Symbiont location on host: endosymbiosis vs. ectosymbiosis

# reordering
dat$endo_or_ecto <- factor(dat$endo_or_ecto, levels = c("Endo/Ecto", "Endo", "Ecto"))

# meta-regression: mutiple intercepts
mr_endo_or_ecto1 <- rma.mv(yi = Zr, V = VZr, mods = ~endo_or_ecto - 1, test = "t", 
    random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_endo_or_ecto2 <- rma.mv(yi = Zr, V = VZr, mods = ~endo_or_ecto, test = "t", random = ~1 | 
    authors, data = dat)

# meta-regression: contrast 2
mr_endo_or_ecto3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(endo_or_ecto, ref = "Endo"), 
    test = "t", random = ~1 | authors, data = dat)

Table S3.6

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with endo_or_ecto. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_endo_or_ecto1 <- R2(mr_endo_or_ecto1)

# getting estimates
res_endo_or_ecto1 <- get_est(mr_endo_or_ecto1, mod = "endo_or_ecto")
res_endo_or_ecto2 <- get_est(mr_endo_or_ecto2, mod = "endo_or_ecto")
res_endo_or_ecto3 <- get_est(mr_endo_or_ecto3, mod = "endo_or_ecto")

# creating a table
tibble(`Fixed effect` = c(as.character(res_endo_or_ecto1$name), as.character(res_endo_or_ecto1$name), 
    cont_gen(res_endo_or_ecto1$name)), Unit = c(rep(c("Zr (mu)", "r (mu)"), each = 3), 
    rep("Zr (beta)", 3)), Estimate = c(res_endo_or_ecto1$estimate, tanh(res_endo_or_ecto1$estimate), 
    res_endo_or_ecto2$estimate[-1], res_endo_or_ecto3$estimate[-(1:2)]), `Lower CI [0.025]` = c(res_endo_or_ecto1$lowerCL, 
    tanh(res_endo_or_ecto1$lowerCL), res_endo_or_ecto2$lowerCL[-1], res_endo_or_ecto3$lowerCL[-(1:2)]), 
    `Upper CI  [0.975]` = c(res_endo_or_ecto1$upperCL, tanh(res_endo_or_ecto1$upperCL), 
        res_endo_or_ecto2$upperCL[-1], res_endo_or_ecto3$upperCL[-(1:2)]), `V[authors]` = c(mr_endo_or_ecto1$sigma2, 
        rep(NA, 8)), R2 = c(r2_endo_or_ecto1[1], rep(NA, 8))) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Endo/Ecto Zr (mu) 0.492 0.029 0.955 0.083 0.002
Endo Zr (mu) 0.530 0.460 0.599 NA NA
Ecto Zr (mu) 0.555 0.451 0.659 NA NA
Endo/Ecto r (mu) 0.456 0.029 0.742 NA NA
Endo r (mu) 0.485 0.430 0.536 NA NA
Ecto r (mu) 0.504 0.423 0.578 NA NA
Endo/Ecto-Endo Zr (beta) 0.037 -0.431 0.506 NA NA
Endo/Ecto-Ecto Zr (beta) 0.063 -0.412 0.537 NA NA
Endo-Ecto Zr (beta) 0.026 -0.100 0.151 NA NA

Figure 4a

# getting images
image_endoparasite <- readPNG(here("images/endoparasite_transparentbg.png"))
image_ectoparasite <- readPNG(here("images/ectoparasite_transparentbg.png"))

# adding sample size (k) for each category
k_endo_or_ecto <- dat %>% group_by(endo_or_ecto) %>% count()
# getting estimates and predicitons
pred_endo_or_ecto <- get_pred(mr_endo_or_ecto1, mod = "endo_or_ecto") 
res_endo_or_ecto1 <- left_join(res_endo_or_ecto1, k_endo_or_ecto, by =  c("name" = "endo_or_ecto"))  %>% left_join(pred_endo_or_ecto)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_endo_or_ecto <- ggplot(data = res_endo_or_ecto1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(endo_or_ecto)), 
                   aes(x= tanh(Zr), y = endo_or_ecto, size = ((1/VZr) + 3), colour = endo_or_ecto), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_fill_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_y_discrete(labels = c("Endo/Ecto" = "Both",  "Endo" = "Endosymbiosis",  "Ecto"= "Ectosymbiosis")) +
  annotate('text', x = 0.93, y = 1:3 + 0.15, label= paste("italic(k)==", res_endo_or_ecto1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction = "horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # adding images
  annotation_custom(rasterGrob(image_endoparasite), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_ectoparasite), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_ectoparasite), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_endoparasite), xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2)

fig_endo_or_ecto

# fig 3e

e <- ggplot(data = res_endo_or_ecto1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(endo_or_ecto)), 
                   aes(x= tanh(Zr), y = endo_or_ecto, size = ((1/VZr) + 3), colour = endo_or_ecto), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_fill_manual(values = c("Endo/Ecto" = "#0072B2",  "Endo" = "#D55E00",  "Ecto"= "#CC79A7")) +
  scale_y_discrete(labels = c("Endo/Ecto" = "Both",  "Endo" = "Endosymbiosis",  "Ecto"= "Ectosymbiosis")) +
  annotate('text', x = 0.93, y = 1:3 + 0.15, label= paste("italic(k)==", res_endo_or_ecto1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = "", y = "", size = expression(paste(italic(n), " (# of species pairs)")), tag = "e" ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # adding images
  annotation_custom(rasterGrob(image_endoparasite), xmin = -1, xmax = -0.8, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_ectoparasite), xmin = -1, xmax = -0.8, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_ectoparasite), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_endoparasite), xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2)

Figure 4a: An orchard plot showing the group-wise means (the categorical variable endo_or_ecto) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

The effect of the mode of transmission

# meta-regression: mutiple intercepts
mr_mode_of_transmission_broad1 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad - 
    1, test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 1
mr_mode_of_transmission_broad2 <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad, 
    test = "t", random = ~1 | authors, data = dat)

# meta-regression: contrast 2
mr_mode_of_transmission_broad3 <- rma.mv(yi = Zr, V = VZr, mods = ~relevel(mode_of_transmission_broad, 
    ref = "vertical"), test = "t", random = ~1 | authors, data = dat)

Table S3.7

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with mode_of_transmission_broad. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_mode_of_transmission_broad1 <- R2(mr_mode_of_transmission_broad1)

# getting estimates
res_mode_of_transmission_broad1 <- get_est(mr_mode_of_transmission_broad1, mod = "mode_of_transmission_broad")
res_mode_of_transmission_broad2 <- get_est(mr_mode_of_transmission_broad2, mod = "mode_of_transmission_broad")
res_mode_of_transmission_broad3 <- get_est(mr_mode_of_transmission_broad3, mod = "mode_of_transmission_broad")

# creating a table
t_transmission <- tibble(`Fixed effect` = c(as.character(res_mode_of_transmission_broad1$name), 
    as.character(res_mode_of_transmission_broad1$name), cont_gen(res_mode_of_transmission_broad1$name)), 
    Unit = c(rep(c("Zr (mu)", "r (mu)"), each = 3), rep("Zr (beta)", 3)), Estimate = c(res_mode_of_transmission_broad1$estimate, 
        tanh(res_mode_of_transmission_broad1$estimate), res_mode_of_transmission_broad2$estimate[-1], 
        res_mode_of_transmission_broad3$estimate[-(1:2)]), `Lower CI [0.025]` = c(res_mode_of_transmission_broad1$lowerCL, 
        tanh(res_mode_of_transmission_broad1$lowerCL), res_mode_of_transmission_broad2$lowerCL[-1], 
        res_mode_of_transmission_broad3$lowerCL[-(1:2)]), `Upper CI  [0.975]` = c(res_mode_of_transmission_broad1$upperCL, 
        tanh(res_mode_of_transmission_broad1$upperCL), res_mode_of_transmission_broad2$upperCL[-1], 
        res_mode_of_transmission_broad3$upperCL[-(1:2)]), `V[authors]` = c(mr_mode_of_transmission_broad1$sigma2, 
        rep(NA, 8)), R2 = c(r2_mode_of_transmission_broad1[1], rep(NA, 8)))

t_transmission %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
both Zr (mu) 0.578 0.463 0.693 0.061 0.187
horizontal Zr (mu) 0.446 0.378 0.515 NA NA
vertical Zr (mu) 0.751 0.634 0.868 NA NA
both r (mu) 0.521 0.432 0.600 NA NA
horizontal r (mu) 0.419 0.361 0.474 NA NA
vertical r (mu) 0.636 0.561 0.701 NA NA
both-horizontal Zr (beta) -0.131 -0.265 0.002 NA NA
both-vertical Zr (beta) 0.174 0.009 0.338 NA NA
horizontal-vertical Zr (beta) -0.305 -0.441 -0.169 NA NA

Figure 4b

# getting images
image_horizontal <- readPNG(here("images/horizontal_transparentbg.png"))
image_vertical <- readPNG(here("images/vertical_transparentbg.png"))
image_both <- readPNG(here("images/horizontal_vertical_transparentbg.png"))
# adding sample size (k) for each category
k_mode_of_transmission_broad <- dat %>% group_by(mode_of_transmission_broad) %>% count()
# getting estimates and predicitons
pred_mode_of_transmission_broad <- get_pred(mr_mode_of_transmission_broad1, mod = "mode_of_transmission_broad") 
res_mode_of_transmission_broad1 <- left_join(res_mode_of_transmission_broad1, k_mode_of_transmission_broad, by =  c("name" = "mode_of_transmission_broad"))  %>% left_join(pred_mode_of_transmission_broad)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_mode_of_transmission_broad <- ggplot(data = res_mode_of_transmission_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(mode_of_transmission_broad)), 
                   aes(x= tanh(Zr), y = mode_of_transmission_broad, size = ((1/VZr) + 3), colour = mode_of_transmission_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_fill_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_y_discrete(labels = c("both" = "Both",  "horizontal" = "Horizontal",  "vertical"= "Vertical")) +
  annotate('text', x = 0.93, y = (1:3 + 0.15), label= paste("italic(k)==", res_mode_of_transmission_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction = "horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # adding images
  annotation_custom(rasterGrob(image_horizontal), xmin = -1, xmax = -0.7, ymin = 1.4, ymax = 2.2) +
  annotation_custom(rasterGrob(image_vertical), xmin = -1, xmax = -0.7, ymin = 2.4, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_both), xmin = -1, xmax = -0.7, ymin = 0.4, ymax = 1.2) 

fig_mode_of_transmission_broad

# fig 3f

f <- ggplot(data = res_mode_of_transmission_broad1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(mode_of_transmission_broad)), 
                   aes(x= tanh(Zr), y = mode_of_transmission_broad, size = ((1/VZr) + 3), colour = mode_of_transmission_broad), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_fill_manual(values = c("both" = "#0072B2",  "horizontal" = "#D55E00",  "vertical"= "#CC79A7")) +
  scale_y_discrete(labels = c("both" = "Both",  "horizontal" = "Horizontal",  "vertical"= "Vertical")) +
  annotate('text', x = 0.93, y = (1:3 + 0.15), label= paste("italic(k)==", res_mode_of_transmission_broad1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = "", y = "", size = expression(paste(italic(n), " (# of species pairs)")), tag = "f" ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # adding images
  annotation_custom(rasterGrob(image_horizontal), xmin = -1, xmax = -0.7, ymin = 1.4, ymax = 2.2) +
  annotation_custom(rasterGrob(image_vertical), xmin = -1, xmax = -0.7, ymin = 2.4, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_both), xmin = -1, xmax = -0.7, ymin = 0.4, ymax = 1.2) 

Figure 4b: An orchard plot showing the group-wise means (the categorical variable mode_of_transmission_broad), indicating 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

The combined effect of symbiosis and mode of transmission

# reordering
dat$symbiosis_transmission <- factor(dat$symbiosis_transmission, levels = c("Mutualistboth", 
    "Mutualisthorizontal", "Mutualistvertical", "Parasiteboth", "Parasitehorizontal"), 
    labels = c("MutualistBoth", "MutualistHorizontal", "MutualistVertical", "ParasiteBoth", 
        "ParasiteHorizontal"))

# meta-regression: mutiple intercepts
mr_symbiosis_transmission1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiosis_transmission - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$symbiosis_transmission)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiosis_transmission, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_symbiosis_transmission <- map(level_names[-length(level_names)], run_rma)

Table S3.8

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with symbiosis_transmission. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_symbiosis_transmission1 <- R2(mr_symbiosis_transmission1)

# getting estimates
res_symbiosis_transmission1 <- get_est(mr_symbiosis_transmission1, mod = "symbiosis_transmission")
res_symbiosis_transmission <- map(mr_symbiosis_transmission, ~get_est(.x, mod = "symbiosis_transmission"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:4)

# you need to flatten twice: first to make it a list and make it a vector
estimates <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_symbiosis_transmission, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiosis_transmission1$name), as.character(res_symbiosis_transmission1$name), 
    cont_gen(res_symbiosis_transmission1$name)), Unit = c(rep(c("Zr (mu)", "r (mu)"), 
    each = 5), rep("Zr (beta)", 10)), Estimate = c(res_symbiosis_transmission1$estimate, 
    tanh(res_symbiosis_transmission1$estimate), estimates), `Lower CI [0.025]` = c(res_symbiosis_transmission1$lowerCL, 
    tanh(res_symbiosis_transmission1$lowerCL), lowerCLs), `Upper CI  [0.975]` = c(res_symbiosis_transmission1$upperCL, 
    tanh(res_symbiosis_transmission1$upperCL), upperCLs), `V[authors]` = c(mr_symbiosis_transmission1$sigma2, 
    rep(NA, (5 + 5 + choose(5, 2)) - 1)), R2 = c(r2_symbiosis_transmission1[1], rep(NA, 
    (5 + 5 + choose(5, 2)) - 1))) %>% kable("html", digits = 3) %>% kable_styling("striped", 
    position = "left") %>% scroll_box(width = "100%", height = "300px")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MutualistBoth Zr (mu) 0.704 0.345 1.063 0.062 0.181
MutualistHorizontal Zr (mu) 0.456 0.297 0.615 NA NA
MutualistVertical Zr (mu) 0.746 0.627 0.865 NA NA
ParasiteBoth Zr (mu) 0.564 0.442 0.686 NA NA
ParasiteHorizontal Zr (mu) 0.445 0.370 0.519 NA NA
MutualistBoth r (mu) 0.607 0.332 0.787 NA NA
MutualistHorizontal r (mu) 0.427 0.289 0.548 NA NA
MutualistVertical r (mu) 0.633 0.556 0.699 NA NA
ParasiteBoth r (mu) 0.511 0.415 0.595 NA NA
ParasiteHorizontal r (mu) 0.418 0.354 0.477 NA NA
MutualistBoth-MutualistHorizontal Zr (beta) -0.248 -0.640 0.145 NA NA
MutualistBoth-MutualistVertical Zr (beta) 0.042 -0.336 0.420 NA NA
MutualistBoth-ParasiteBoth Zr (beta) -0.140 -0.519 0.239 NA NA
MutualistBoth-ParasiteHorizontal Zr (beta) -0.259 -0.625 0.107 NA NA
MutualistHorizontal-MutualistVertical Zr (beta) 0.290 0.091 0.488 NA NA
MutualistHorizontal-ParasiteBoth Zr (beta) 0.108 -0.093 0.308 NA NA
MutualistHorizontal-ParasiteHorizontal Zr (beta) -0.011 -0.183 0.161 NA NA
MutualistVertical-ParasiteBoth Zr (beta) -0.182 -0.352 -0.012 NA NA
MutualistVertical-ParasiteHorizontal Zr (beta) -0.301 -0.441 -0.161 NA NA
ParasiteBoth-ParasiteHorizontal Zr (beta) -0.119 -0.262 0.024 NA NA

Figure 4c

# colour list
colour_ls <- c("#000000", "#E69F00", "#56B4E9", "#009E73",  "#F0E422",  "#0072B2",  "#D55E00", "#CC79A7", "#00008B", "#8B0A50", "#54FF9F", "#999999")

# adding sample size (k) for each category
k_symbiosis_transmission <- dat %>% group_by(symbiosis_transmission) %>% count()
# getting estimates and predicitons
pred_symbiosis_transmission <- get_pred(mr_symbiosis_transmission1, mod = "symbiosis_transmission") 
res_symbiosis_transmission1 <- left_join(res_symbiosis_transmission1, k_symbiosis_transmission, by =  c("name" = "symbiosis_transmission"))  %>% left_join(pred_symbiosis_transmission)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiosis_transmission <- ggplot(data = res_symbiosis_transmission1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis_transmission)), 
                   aes(x= tanh(Zr), y = symbiosis_transmission, size = ((1/VZr) + 3), colour = symbiosis_transmission), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =   c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_fill_manual(values = c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_y_discrete(labels = c("MutualistBoth" = "Mutualist-\nBoth", "MutualistHorizontal" = "Mutualist-\nHorizontal","MutualistVertical" = "Mutualist-\nVertical", "ParasiteBoth" = "Parasite-\nBoth", "ParasiteHorizontal" = "Parasite-\nHorizontal")) +
  annotate('text', x = 0.93, y = 1:5 + 0.15, label= paste("italic(k)==", res_symbiosis_transmission1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_both), xmin = -0.9, xmax = -0.6, ymin = 0.4, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_horizontal),xmin = -0.9, xmax = -0.6, ymin = 1.4, ymax = 2.2) +
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertical), xmin = -0.9, xmax = -0.6, ymin = 2.4, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -1.1, xmax = -0.9, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_both), xmin = -0.9, xmax = -0.6, ymin = 3.4, ymax = 4.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -1.1, xmax = -0.9, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_horizontal), xmin = -0.9, xmax = -0.6, ymin = 4.4, ymax = 5.2)

fig_symbiosis_transmission

## fig 3
g <- ggplot(data = res_symbiosis_transmission1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiosis_transmission)), 
                   aes(x= tanh(Zr), y = symbiosis_transmission, size = ((1/VZr) + 3), colour = symbiosis_transmission), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =   c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_fill_manual(values = c("MutualistBoth"= colour_ls[1], "MutualistHorizontal"= colour_ls[2], "MutualistVertical" = colour_ls[3],"ParasiteBoth"= colour_ls[4], "ParasiteHorizontal" = colour_ls[5])) +
  scale_y_discrete(labels = c("MutualistBoth" = "Mutualist-\nBoth", "MutualistHorizontal" = "Mutualist-\nHorizontal","MutualistVertical" = "Mutualist-\nVertical", "ParasiteBoth" = "Parasite-\nBoth", "ParasiteHorizontal" = "Parasite-\nHorizontal")) +
  annotate('text', x = 0.93, y = 1:5 + 0.15, label= paste("italic(k)==", res_symbiosis_transmission1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ,tag = "g" ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position="none") +
  theme(axis.text.y = element_text(size = 10, colour ="black",hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_both), xmin = -0.9, xmax = -0.6, ymin = 0.4, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_horizontal),xmin = -0.9, xmax = -0.6, ymin = 1.4, ymax = 2.2) +
  annotation_custom(rasterGrob(image_mutualism), xmin = -1.1, xmax = -0.9, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_vertical), xmin = -0.9, xmax = -0.6, ymin = 2.4, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -1.1, xmax = -0.9, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_both), xmin = -0.9, xmax = -0.6, ymin = 3.4, ymax = 4.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -1.1, xmax = -0.9, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_horizontal), xmin = -0.9, xmax = -0.6, ymin = 4.4, ymax = 5.2)

Figure 4c: An orchard plot showing the group-wise means (the categorical variable symbiosis_transmission) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

Putting together Figure 3

# building fig 3 using patchwork
fig3 <- (a/b/c/d + plot_layout(heights = c(1.6, 2, 3.7, 3.7)))


# fig3 <- (a / b / c / d + plot_layout(heights = c(1.6, 2, 3.7, 3.7))) | (e / f /
# g + plot_layout(heights = c(2.8, 2.8, 4.4))) #+ plot_annotation(tag_levels =
# 'a', tag_suffix = ')')

fig3

# ggsave(here('figs/fig3.png'), width = 8, height = 12)
# ggsave(here('figs/fig3.pdf'), width = 8, height = 12)

Figure 3: putting all 4 panels together: Figure 3a - Figure 3d (see the main text)

Putting together Figure 4

# building fig 3 using patchwork
fig4 <- (e/f/g + plot_layout(heights = c(2.8, 2.8, 4.4))) + plot_annotation(tag_levels = "a")

fig4

# ggsave(here('figs/fig4.png'), width = 8, height = 12)
# ggsave(here('figs/fig4.pdf'), width = 8, height = 12)

Figure 4: putting all 3 panels together: Figure 4a - Figure 4c (see the main text)

Additional analyses (uni-predictor)

These are extra analyses not discussed in the main text.

The combined effect of host taxa and symbiosis (parasitism vs. mutualism)

# reordering
dat$host_tax_symbiosis <- factor(dat$host_tax_symbiosis, levels = c("MicrobeMutualist", 
    "MicrobeParasite", "PlantMutualist", "PlantParasite", "InvertMutualist", "InvertParasite", 
    "VertMutualist", "VertParasite"))

# meta-regression: mutiple intercepts
mr_host_tax_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_symbiosis - 1, 
    test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$host_tax_symbiosis)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_tax_symbiosis, ref = name), test = "t", 
        random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_host_tax_symbiosis <- map(level_names[-length(level_names)], run_rma)

Table S3.9

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with host_tax_symbiosis. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_host_tax_symbiosis1 <- R2(mr_host_tax_symbiosis1)

# getting estimates
res_host_tax_symbiosis1 <- get_est(mr_host_tax_symbiosis1, mod = "host_tax_symbiosis")
res_host_tax_symbiosis <- map(mr_host_tax_symbiosis, ~get_est(.x, mod = "host_tax_symbiosis"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:7)

# you need to flatten twice: first to make it a list and make it a vector
estimates <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_host_tax_symbiosis, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_host_tax_symbiosis1$name), cont_gen(res_host_tax_symbiosis1$name)), 
    Estimate = c(res_host_tax_symbiosis1$estimate, estimates), `Lower CI [0.025]` = c(res_host_tax_symbiosis1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_host_tax_symbiosis1$upperCL, upperCLs), 
    `V[authors]` = c(mr_host_tax_symbiosis1$sigma2, rep(NA, (8 + choose(8, 2)) - 
        1)), R2 = c(r2_host_tax_symbiosis1[1], rep(NA, (8 + choose(8, 2)) - 1))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left") %>% 
    scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeMutualist 1.316 0.982 1.650 0.069 0.311
MicrobeParasite 0.419 0.082 0.755 NA NA
PlantMutualist 0.373 0.197 0.548 NA NA
PlantParasite 0.379 0.237 0.521 NA NA
InvertMutualist 0.638 0.520 0.757 NA NA
InvertParasite 0.552 0.336 0.768 NA NA
VertMutualist 1.166 0.294 2.038 NA NA
VertParasite 0.505 0.427 0.583 NA NA
MicrobeMutualist-MicrobeParasite -0.898 -1.372 -0.423 NA NA
MicrobeMutualist-PlantMutualist -0.943 -1.320 -0.566 NA NA
MicrobeMutualist-PlantParasite -0.937 -1.300 -0.575 NA NA
MicrobeMutualist-InvertMutualist -0.678 -1.032 -0.324 NA NA
MicrobeMutualist-InvertParasite -0.764 -1.162 -0.367 NA NA
MicrobeMutualist-VertMutualist -0.150 -1.084 0.783 NA NA
MicrobeMutualist-VertParasite -0.811 -1.154 -0.469 NA NA
MicrobeParasite-PlantMutualist -0.046 -0.425 0.334 NA NA
MicrobeParasite-PlantParasite -0.040 -0.405 0.326 NA NA
MicrobeParasite-InvertMutualist 0.220 -0.137 0.577 NA NA
MicrobeParasite-InvertParasite 0.133 -0.267 0.533 NA NA
MicrobeParasite-VertMutualist 0.748 -0.187 1.682 NA NA
MicrobeParasite-VertParasite 0.086 -0.259 0.432 NA NA
PlantMutualist-PlantParasite 0.006 -0.206 0.218 NA NA
PlantMutualist-InvertMutualist 0.266 0.054 0.477 NA NA
PlantMutualist-InvertParasite 0.179 -0.099 0.457 NA NA
PlantMutualist-VertMutualist 0.793 -0.096 1.683 NA NA
PlantMutualist-VertParasite 0.132 -0.060 0.324 NA NA
PlantParasite-InvertMutualist 0.260 0.075 0.444 NA NA
PlantParasite-InvertParasite 0.173 -0.085 0.431 NA NA
PlantParasite-VertMutualist 0.787 -0.096 1.671 NA NA
PlantParasite-VertParasite 0.126 -0.036 0.288 NA NA
InvertMutualist-InvertParasite -0.087 -0.333 0.159 NA NA
InvertMutualist-VertMutualist 0.528 -0.352 1.408 NA NA
InvertMutualist-VertParasite -0.133 -0.275 0.008 NA NA
InvertParasite-VertMutualist 0.614 -0.284 1.512 NA NA
InvertParasite-VertParasite -0.047 -0.270 0.176 NA NA
VertMutualist-VertParasite -0.661 -1.536 0.214 NA NA

Figure S3.3

# adding sample size (k) for each category
k_host_tax_symbiosis <- dat %>% group_by(host_tax_symbiosis) %>% count()
# getting estimates and predicitons
pred_host_tax_symbiosis <- get_pred(mr_host_tax_symbiosis1, mod = "host_tax_symbiosis") 
res_host_tax_symbiosis1 <- left_join(res_host_tax_symbiosis1, k_host_tax_symbiosis, by =  c("name" = "host_tax_symbiosis"))  %>% left_join(pred_host_tax_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_tax_symbiosis <- ggplot(data = res_host_tax_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_tax_symbiosis)), 
                   aes(x= tanh(Zr), y = host_tax_symbiosis, size = ((1/VZr) + 3), colour = host_tax_symbiosis), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =   c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertMutualist"= colour_ls[7],     "VertParasite"= colour_ls[8] )) +
  scale_fill_manual(values = c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertMutualist"= colour_ls[7],     "VertParasite"= colour_ls[8] )) +
  scale_y_discrete(labels = c("MicrobeMutualist"= "Microbe-\nMutualist", "MicrobeParasite"= "Microbe-\nParasite",  "PlantMutualist" = "Plant-\nMutualist", "PlantParasite"="Plant-\nParasite", "InvertMutualist" = "Invertebrate-\nMutualist",   "InvertParasite"= "Invertebrate-\nParasite", "VertMutualist"= "Vertebrate-\nMutualist",  "VertParasite"= "Vertebrate-\nParasite" )) +
  annotate('text', x = 0.93, y = 1:8 + 0.15, label= paste("italic(k)==", res_host_tax_symbiosis1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
  # putting pictures in
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1.1, xmax = -0.9, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_parasitism),xmin = -0.9, xmax = -0.7, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_plant_host), xmin = -1.1, xmax = -0.9, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_plant_host), xmin = -1.1, xmax = -0.9, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 6.6, ymax = 7.2) +
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 6.6, ymax = 7.2) +
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 7.6, ymax = 8.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 7.6, ymax = 8.2)

fig_host_tax_symbiosis

Figure S3.3: An orchard plot showing group-wise means (the categorical variable host_tax_symbiosis) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

Splitting host taxonomy by mode of symbiosis revealed that the observed higher phylogenetic congruence of host-symbiont cophylogenies involving a microbial host is driven primarily by greater congruence between microbial hosts and mutualist symbionts. Congruence is also relatively high for invertebrate hosts that harbour a mutualistic symbiont, while congruence appears to be lowest for plant hosts that harbour a parasitic symbiont.

The combined effect of symbiont taxa and symbiosis (parasitism vs. mutualism)

# reordering
dat$symbiont_tax_symbiosis <- factor(dat$symbiont_tax_symbiosis, levels = c("MicrobeMutualist", 
    "MicrobeParasite", "PlantMutualist", "PlantParasite", "InvertMutualist", "InvertParasite", 
    "VertParasite"))

# meta-regression: multiple intercepts
mr_symbiont_tax_symbiosis1 <- rma.mv(yi = Zr, V = VZr, mods = ~symbiont_tax_symbiosis - 
    1, test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$symbiont_tax_symbiosis)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(symbiont_tax_symbiosis, ref = name), 
        test = "t", random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_symbiont_tax_symbiosis <- map(level_names[-length(level_names)], run_rma)

Table S3.10

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with symbiont_tax_symbiosis. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_symbiont_tax_symbiosis1 <- R2(mr_symbiont_tax_symbiosis1)

# getting estimates
res_symbiont_tax_symbiosis1 <- get_est(mr_symbiont_tax_symbiosis1, mod = "symbiont_tax_symbiosis")
res_symbiont_tax_symbiosis <- map(mr_symbiont_tax_symbiosis, ~get_est(.x, mod = "symbiont_tax_symbiosis"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:6)

# you need to flatten twice: first to make it a list and make it a vector
estimates <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()
lowerCLs <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "lowerCL"]) %>% 
    flatten() %>% flatten_dbl()
upperCLs <- map2(res_symbiont_tax_symbiosis, contra_list, ~.x[-(.y), "upperCL"]) %>% 
    flatten() %>% flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiont_tax_symbiosis1$name), cont_gen(res_symbiont_tax_symbiosis1$name)), 
    Estimate = c(res_symbiont_tax_symbiosis1$estimate, estimates), `Lower CI [0.025]` = c(res_symbiont_tax_symbiosis1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_symbiont_tax_symbiosis1$upperCL, upperCLs), 
    `V[authors]` = c(mr_symbiont_tax_symbiosis1$sigma2, rep(NA, (7 + choose(7, 2)) - 
        1)), R2 = c(r2_symbiont_tax_symbiosis1[1], rep(NA, (7 + choose(7, 2)) - 1))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left") %>% 
    scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeMutualist 0.670 0.557 0.782 0.075 0.389
MicrobeParasite 0.435 0.330 0.539 NA NA
PlantMutualist 1.009 0.536 1.482 NA NA
PlantParasite 3.453 1.411 5.496 NA NA
InvertMutualist 0.445 0.248 0.641 NA NA
InvertParasite 0.510 0.422 0.597 NA NA
VertParasite 0.440 -0.173 1.053 NA NA
MicrobeMutualist-MicrobeParasite -0.235 -0.388 -0.082 NA NA
MicrobeMutualist-PlantMutualist 0.339 -0.147 0.826 NA NA
MicrobeMutualist-PlantParasite 2.784 0.738 4.830 NA NA
MicrobeMutualist-InvertMutualist -0.225 -0.452 0.002 NA NA
MicrobeMutualist-InvertParasite -0.160 -0.303 -0.018 NA NA
MicrobeMutualist-VertParasite -0.230 -0.853 0.394 NA NA
MicrobeParasite-PlantMutualist 0.574 0.090 1.059 NA NA
MicrobeParasite-PlantParasite 3.019 0.973 5.064 NA NA
MicrobeParasite-InvertMutualist 0.010 -0.213 0.233 NA NA
MicrobeParasite-InvertParasite 0.075 -0.061 0.211 NA NA
MicrobeParasite-VertParasite 0.005 -0.616 0.627 NA NA
PlantMutualist-PlantParasite 2.444 0.347 4.541 NA NA
PlantMutualist-InvertMutualist -0.564 -1.077 -0.052 NA NA
PlantMutualist-InvertParasite -0.499 -0.981 -0.018 NA NA
PlantMutualist-VertParasite -0.569 -1.343 0.205 NA NA
PlantParasite-InvertMutualist -3.009 -5.061 -0.956 NA NA
PlantParasite-InvertParasite -2.944 -4.989 -0.899 NA NA
PlantParasite-VertParasite -3.013 -5.146 -0.880 NA NA
InvertMutualist-InvertParasite 0.065 -0.143 0.273 NA NA
InvertMutualist-VertParasite -0.005 -0.648 0.639 NA NA
InvertParasite-VertParasite -0.070 -0.689 0.550 NA NA

Figure S3.4

# adding sample size (k) for each category
k_symbiont_tax_symbiosis <- dat %>% group_by(symbiont_tax_symbiosis) %>% count()
# getting estimates and predicitons
pred_symbiont_tax_symbiosis <- get_pred(mr_symbiont_tax_symbiosis1, mod = "symbiont_tax_symbiosis") 
res_symbiont_tax_symbiosis1 <- left_join(res_symbiont_tax_symbiosis1, k_symbiont_tax_symbiosis, by =  c("name" = "symbiont_tax_symbiosis"))  %>% left_join(pred_symbiont_tax_symbiosis)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_symbiont_tax_symbiosis <- ggplot(data = res_symbiont_tax_symbiosis1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(symbiont_tax_symbiosis)), 
                   aes(x= tanh(Zr), y = symbiont_tax_symbiosis, size = ((1/VZr) + 3), colour = symbiont_tax_symbiosis), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  # setting colours
  scale_color_manual(values =   c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertParasite"= colour_ls[8] )) +
  scale_fill_manual(values = c("MicrobeMutualist"= colour_ls[1], "MicrobeParasite"= colour_ls[2],  "PlantMutualist"= colour_ls[3], "PlantParasite"= colour_ls[4], "InvertMutualist" = colour_ls[5],  "InvertParasite"= colour_ls[6], "VertParasite"= colour_ls[8] )) +
  scale_y_discrete(labels = c("MicrobeMutualist"= "Microbe-\nMutualist", "MicrobeParasite"= "Microbe-\nParasite",  "PlantMutualist" = "Plant-\nMutualist", "PlantParasite"="Plant-\nParasite", "InvertMutualist" = "Invertebrate-\nMutualist",   "InvertParasite"= "Invertebrate-\nParasite",  "VertParasite"= "Vertebrate-\nParasite" )) +
  annotate('text', x = 0.93, y = 1:7 + 0.15, label= paste("italic(k)==", res_symbiont_tax_symbiosis1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
    # putting pictures in
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -1.1, xmax = -0.9, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_parasitism),xmin = -0.9, xmax = -0.7, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -1.1, xmax = -0.9, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -1.1, xmax = -0.9, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -1.1, xmax = -0.9, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_mutualism), xmin = -0.9, xmax = -0.7, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -1.1, xmax = -0.9, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_vertebrate_parasite), xmin = -1.1, xmax = -0.9, ymin = 6.6, ymax = 7.2) +
  annotation_custom(rasterGrob(image_parasitism), xmin = -0.9, xmax = -0.7, ymin = 6.6, ymax = 7.2) 

fig_symbiont_tax_symbiosis

Figure S3.4: An orchard plot showing group-wise means (the categorical variable symbiont_tax_symbiosis) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

Splitting symbiont taxonomy by mode of symbiosis revealed much less variation, except for higher congruence exhibited by cophylogenies involving a plant symbiont (instances of which are relatively rare), and the finding that cophylogenies involving a microbial mutualist symbiont are slightly more congruent than the remaining categories.

The combined effect of host and symbiont taxa

# reordering
dat$host_symbiont_tax <- factor(dat$host_symbiont_tax, levels = c("MicrobeInvert", 
    "MicrobeMicrobe", "MicrobePlant", "PlantInvert", "PlantMicrobe", "InvertInvert", 
    "InvertMicrobe", "InvertPlant", "VertInvert", "VertMicrobe", "VertVert"))

# meta-regression: multiple intercepts
mr_host_symbiont_tax1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_symbiont_tax - 1, 
    test = "t", random = ~1 | authors, data = dat)

# # meta-regression: contrasts x 10 getting the level names out
level_names <- levels(dat$host_symbiont_tax)

# helper function to run metafor meta-regression
run_rma <- function(name) {
    rma.mv(yi = Zr, V = VZr, mods = ~relevel(host_symbiont_tax, ref = name), test = "t", 
        random = ~1 | authors, data = dat)
}

# results of meta-regression including all contrast results; taking the last
# level out ([-length(level_names)])
mr_host_symbiont_tax <- map(level_names[-length(level_names)], run_rma)

Table S3.11

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with host_symbiont_tax. Note that mu means the group mean while beta represents the contrast between two groups in the Unit column.

# getting marginal R2
r2_host_symbiont_tax1 <- R2(mr_host_symbiont_tax1)

# getting estimates
res_host_symbiont_tax1 <- get_est(mr_host_symbiont_tax1, mod = "host_symbiont_tax")
res_host_symbiont_tax <- map(mr_host_symbiont_tax, ~get_est(.x, mod = "host_symbiont_tax"))

# a list of the numbers to take out unnecessary contrasts
contra_list <- Map(seq, from = 1, to = 1:10)

# you need to flatten twice: first to make it a list and make it a vector
estimates <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "estimate"]) %>% 
    flatten() %>% flatten_dbl()

lowerCLs <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "lowerCL"]) %>% flatten() %>% 
    flatten_dbl()

upperCLs <- map2(res_host_symbiont_tax, contra_list, ~.x[-(.y), "upperCL"]) %>% flatten() %>% 
    flatten_dbl()

# creating a table
tibble(`Fixed effect` = c(as.character(res_host_symbiont_tax1$name), cont_gen(res_host_symbiont_tax1$name)), 
    Estimate = c(res_host_symbiont_tax1$estimate, estimates), `Lower CI [0.025]` = c(res_host_symbiont_tax1$lowerCL, 
        lowerCLs), `Upper CI  [0.975]` = c(res_host_symbiont_tax1$upperCL, upperCLs), 
    `V[authors]` = c(mr_host_tax_symbiosis1$sigma2, rep(NA, (11 + choose(11, 2)) - 
        1)), R2 = c(r2_host_symbiont_tax1[1], rep(NA, (11 + choose(11, 2)) - 1))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left") %>% 
    scroll_box(width = "100%", height = "300px")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
MicrobeInvert 1.069 -0.196 2.335 0.069 0.23
MicrobeMicrobe 0.820 0.532 1.107 NA NA
MicrobePlant 1.055 0.552 1.558 NA NA
PlantInvert 0.329 0.176 0.482 NA NA
PlantMicrobe 0.460 0.258 0.662 NA NA
InvertInvert 0.661 0.449 0.874 NA NA
InvertMicrobe 0.612 0.487 0.738 NA NA
InvertPlant 1.665 0.399 2.931 NA NA
VertInvert 0.562 0.454 0.669 NA NA
VertMicrobe 0.459 0.335 0.584 NA NA
VertVert 0.440 -0.187 1.067 NA NA
MicrobeInvert-MicrobeMicrobe -0.250 -1.547 1.048 NA NA
MicrobeInvert-MicrobePlant -0.014 -1.376 1.348 NA NA
MicrobeInvert-PlantInvert -0.740 -2.015 0.535 NA NA
MicrobeInvert-PlantMicrobe -0.609 -1.891 0.672 NA NA
MicrobeInvert-InvertInvert -0.408 -1.691 0.875 NA NA
MicrobeInvert-InvertMicrobe -0.457 -1.728 0.815 NA NA
MicrobeInvert-InvertPlant 0.596 -1.194 2.386 NA NA
MicrobeInvert-VertInvert -0.507 -1.777 0.763 NA NA
MicrobeInvert-VertMicrobe -0.610 -1.881 0.662 NA NA
MicrobeInvert-VertVert -0.629 -2.041 0.783 NA NA
MicrobeMicrobe-MicrobePlant 0.236 -0.343 0.815 NA NA
MicrobeMicrobe-PlantInvert -0.491 -0.816 -0.165 NA NA
MicrobeMicrobe-PlantMicrobe -0.360 -0.711 -0.008 NA NA
MicrobeMicrobe-InvertInvert -0.158 -0.516 0.199 NA NA
MicrobeMicrobe-InvertMicrobe -0.207 -0.520 0.106 NA NA
MicrobeMicrobe-InvertPlant 0.845 -0.452 2.143 NA NA
MicrobeMicrobe-VertInvert -0.258 -0.564 0.049 NA NA
MicrobeMicrobe-VertMicrobe -0.360 -0.673 -0.047 NA NA
MicrobeMicrobe-VertVert -0.379 -1.069 0.310 NA NA
MicrobePlant-PlantInvert -0.726 -1.252 -0.201 NA NA
MicrobePlant-PlantMicrobe -0.595 -1.137 -0.053 NA NA
MicrobePlant-InvertInvert -0.394 -0.940 0.152 NA NA
MicrobePlant-InvertMicrobe -0.443 -0.961 0.075 NA NA
MicrobePlant-InvertPlant 0.610 -0.752 1.972 NA NA
MicrobePlant-VertInvert -0.493 -1.007 0.021 NA NA
MicrobePlant-VertMicrobe -0.596 -1.114 -0.078 NA NA
MicrobePlant-VertVert -0.615 -1.418 0.188 NA NA
PlantInvert-PlantMicrobe 0.131 -0.122 0.384 NA NA
PlantInvert-InvertInvert 0.332 0.070 0.594 NA NA
PlantInvert-InvertMicrobe 0.283 0.086 0.481 NA NA
PlantInvert-InvertPlant 1.336 0.061 2.611 NA NA
PlantInvert-VertInvert 0.233 0.046 0.420 NA NA
PlantInvert-VertMicrobe 0.130 -0.067 0.327 NA NA
PlantInvert-VertVert 0.111 -0.534 0.756 NA NA
PlantMicrobe-InvertInvert 0.201 -0.092 0.495 NA NA
PlantMicrobe-InvertMicrobe 0.152 -0.085 0.390 NA NA
PlantMicrobe-InvertPlant 1.205 -0.077 2.487 NA NA
PlantMicrobe-VertInvert 0.102 -0.127 0.331 NA NA
PlantMicrobe-VertMicrobe -0.001 -0.238 0.237 NA NA
PlantMicrobe-VertVert -0.020 -0.678 0.638 NA NA
InvertInvert-InvertMicrobe -0.049 -0.296 0.198 NA NA
InvertInvert-InvertPlant 1.004 -0.280 2.287 NA NA
InvertInvert-VertInvert -0.099 -0.326 0.127 NA NA
InvertInvert-VertMicrobe -0.202 -0.448 0.044 NA NA
InvertInvert-VertVert -0.221 -0.883 0.441 NA NA
InvertMicrobe-InvertPlant 1.053 -0.219 2.324 NA NA
InvertMicrobe-VertInvert -0.051 -0.216 0.114 NA NA
InvertMicrobe-VertMicrobe -0.153 -0.329 0.023 NA NA
InvertMicrobe-VertVert -0.172 -0.811 0.467 NA NA
InvertPlant-VertInvert -1.103 -2.373 0.167 NA NA
InvertPlant-VertMicrobe -1.206 -2.477 0.066 NA NA
InvertPlant-VertVert -1.225 -2.637 0.187 NA NA
VertInvert-VertMicrobe -0.103 -0.267 0.062 NA NA
VertInvert-VertVert -0.122 -0.758 0.514 NA NA
VertMicrobe-VertVert -0.019 -0.658 0.620 NA NA

Figure S3.5

# colour list
#colour_ls <- c("#000000", "#E69F00", "#56B4E9", "#009E73",  "#F0E422",  "#0072B2",  "#D55E00", "#CC79A7", "#00008B", "#8B0A50", "#54FF9F", "#999999")

# adding sample size (k) for each category
k_host_symbiont_tax <- dat %>% group_by(host_symbiont_tax) %>% count()
# getting estimates and predicitons
pred_host_symbiont_tax <- get_pred(mr_host_symbiont_tax1, mod = "host_symbiont_tax") 
res_host_symbiont_tax1 <- left_join(res_host_symbiont_tax1, k_host_symbiont_tax, by =  c("name" = "host_symbiont_tax"))  %>% left_join(pred_host_symbiont_tax)
#res_symbiosis1 
# drawing a funnel plot - fig 2b
fig_host_symbiont_tax <- ggplot(data = res_host_symbiont_tax1, aes(x = tanh(estimate), y = name)) +
  scale_x_continuous(limits=c(-1, 1), breaks = seq(-1, 1, by = 0.2) ) +
  geom_quasirandom(data = dat %>% filter(!is.na(host_symbiont_tax)), 
                   aes(x= tanh(Zr), y = host_symbiont_tax, size = ((1/VZr) + 3), colour = host_symbiont_tax), groupOnX = FALSE, alpha=0.4) + 
  # 95 %precition interval (PI)
  geom_errorbarh(aes(xmin = tanh(lowerPR), xmax = tanh(upperPR)),  height = 0, show.legend = F, size = 0.5, alpha = 0.6) +
  # 95 %CI
  geom_errorbarh(aes(xmin = tanh(lowerCL), xmax = tanh(upperCL)),  height = 0, show.legend = F, size = 1.2) +
  geom_vline(xintercept = 0, linetype = 2, colour = "black", alpha = 0.3) +
  # creating dots and different size (bee-swarm and bubbles)
  geom_point(aes(fill = name), size = 3, shape = 21) + #
  # setting colours
  scale_color_manual(values =  c("MicrobeInvert" = colour_ls[1],  "MicrobeMicrobe"= colour_ls[2], "MicrobePlant" = colour_ls[3], "PlantInvert" = colour_ls[4],"PlantMicrobe" = colour_ls[5], "InvertInvert"  = colour_ls[6],  "InvertMicrobe" = colour_ls[7], "InvertPlant" = colour_ls[8],"VertInvert"  = colour_ls[9], "VertMicrobe"= colour_ls[10],"VertVert"  = colour_ls[11])) +
  scale_fill_manual(values = c("MicrobeInvert" = colour_ls[1],  "MicrobeMicrobe"= colour_ls[2], "MicrobePlant" = colour_ls[3], "PlantInvert" = colour_ls[4],"PlantMicrobe" = colour_ls[5], "InvertInvert"  = colour_ls[6],  "InvertMicrobe" = colour_ls[7], "InvertPlant" = colour_ls[8],"VertInvert"  = colour_ls[9], "VertMicrobe"= colour_ls[10],"VertVert"  = colour_ls[11])) +
  scale_y_discrete(labels = c("MicrobeInvert" = "Microbe-\nInvertebrate",  "MicrobeMicrobe"= "Microbe-\nMicrobe", "MicrobePlant" = "Microbe-\nPlant", "PlantInvert" = "Plant-\nInvertebrate","PlantMicrobe" = "Plant-\nMicrobe", "InvertInvert"  = "Invertebrate\nInvertebrate",  "InvertMicrobe" = "Invertebrate-\nMicrobe", "InvertPlant" = "Invertebrate-\nPlant","VertInvert"  = "Vertebrate-\nInvertebrate", "VertMicrobe"= "Vertebrate-\nMicrobe", "VertVert"  = "Vertebrate-\nVertebrate")) +
  annotate('text', x = 0.93, y = 1:11 + 0.15, label= paste("italic(k)==", res_host_symbiont_tax1$n), parse=TRUE, hjust = "left", size=3.5) +
  labs(x = expression(paste(italic(r), " (correlation)")), y = "", size = expression(paste(italic(n), " (# of species pairs)")) ) +
  guides(fill = "none", colour = "none") +
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0,1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) +
    # putting pictures in
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1.1, xmax = -0.9, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -0.9, xmax = -0.7, ymin = 0.6, ymax = 1.2) + 
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1.1, xmax = -0.9, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_microbe_parasite),xmin = -0.9, xmax = -0.7, ymin = 1.6, ymax = 2.2) +
  annotation_custom(rasterGrob(image_microbe_host), xmin = -1.1, xmax = -0.9, ymin = 2.6, ymax = 3.2) + 
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -0.9, xmax = -0.7, ymin = 2.6, ymax = 3.2) + 
  #
  annotation_custom(rasterGrob(image_plant_host), xmin = -1.1, xmax = -0.9, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -0.9, xmax = -0.7, ymin = 3.6, ymax = 4.2) +
  annotation_custom(rasterGrob(image_plant_host), xmin = -1.1, xmax = -0.9, ymin = 4.6, ymax = 5.2) +
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -0.9, xmax = -0.7, ymin = 4.6, ymax = 5.2) +
  #
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -0.9, xmax = -0.7, ymin = 5.6, ymax = 6.2) + 
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 6.6, ymax = 7.2) +
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -0.9, xmax = -0.7, ymin = 6.6, ymax = 7.2) +
  annotation_custom(rasterGrob(image_invertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 7.6, ymax = 8.2) +
  annotation_custom(rasterGrob(image_plant_parasite), xmin = -0.9, xmax = -0.7, ymin = 7.6, ymax = 8.2) +
  #
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 8.6, ymax = 9.2) + 
  annotation_custom(rasterGrob(image_invertebrate_parasite), xmin = -0.9, xmax = -0.7, ymin = 8.6, ymax = 9.2) + 
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 9.6, ymax = 10.2) +
  annotation_custom(rasterGrob(image_microbe_parasite), xmin = -0.9, xmax = -0.7, ymin = 9.6, ymax = 10.2) +
  annotation_custom(rasterGrob(image_vertebrate_host), xmin = -1.1, xmax = -0.9, ymin = 10.6, ymax = 11.2) +
  annotation_custom(rasterGrob(image_vertebrate_parasite), xmin = -0.9, xmax = -0.7, ymin = 10.6, ymax = 11.2)


fig_host_symbiont_tax

Figure S3.5: An orchard plot showing the group-wise means (the categorical variable host_symbiont_tax) with their 95% confidence intervals (thick lines) and 95% prediction intervals (thin lines), with observed effect sizes based on various sample sizes.

Model selection (multi-predictor model)

Here we build the best model via an AICc based model selection method implemented in the R package MuMin(Barton 2009). For the full model, we had 6 variables: symbiosis, host_tax_broad, symbiont_tax_broad, mode_of_transmission_broad, endo_or_ecto, & log(host_range_link_ratio). We did not use log(host_range_taxonomic_breadth) as it is co-linear with log(host_range_link_ratio) and also many of the interaction terms.

# creates a new function to run in MuMIn
updated.rma.mv <- updateable(rma.mv)
# updated.rma.mv

# testing the new function use method = 'ML' so that we can compare AIC
mr_full <- updated.rma.mv(yi = Zr, V = VZr, mods = ~symbiosis + host_tax_broad + 
    symbiont_tax_broad + mode_of_transmission_broad + endo_or_ecto + log(host_range_link_ratio), 
    test = "t", random = ~1 | authors, method = "ML", data = dat)

# ============================= additional methods for 'rma.mv' class (made by
# Kamil Barton) we need this to run model selection with rma.mv in MuMIn
# =============================
formula.rma.mv <- function(x, ...) return(eval(getCall(x)$mods))

makeArgs.rma.mv <- function(obj, termNames, comb, opt, ...) {
    ret <- MuMIn:::makeArgs.default(obj, termNames, comb, opt)
    names(ret)[1L] <- "mods"
    ret
}

nobs.rma.mv <- function(object, ...) attr(logLik(object), "nall")

coefTable.rma.mv <- function(model, ...) MuMIn:::.makeCoefTable(model$b, model$se, 
    coefNames = rownames(model$b))
# =============================

# testing dredge dredge(full.model, evaluate=F) # show all candidate models n =
# 32 model exisit
candidates <- dredge(mr_full)

# displays delta AICc <2
candidates_aic2 <- subset(candidates, delta < 2)

# model averaging it seems like models are using z values rather than t values
# (which will be OK)
mr_averaged_aic2 <- summary(model.avg(candidates, delta < 2))

# relative importance of each predictor
importance <- importance(candidates)

# use REML if not for model comparision
model1 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad + mode_of_transmission_broad + 
    symbiosis, test = "t", random = ~1 | authors, method = "REML", data = dat)
model2 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad + mode_of_transmission_broad, 
    test = "t", random = ~1 | authors, method = "REML", data = dat)
model3 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad + log(host_range_link_ratio) + 
    mode_of_transmission_broad + symbiosis, test = "t", random = ~1 | authors, method = "REML", 
    data = dat)
model4 <- rma.mv(yi = Zr, V = VZr, mods = ~host_tax_broad + log(host_range_link_ratio) + 
    mode_of_transmission_broad, test = "t", random = ~1 | authors, method = "REML", 
    data = dat)

Table 3.12

The top 4 models (out of 32 possible models) within the \(\Delta\)AIC difference of 2, and which 6 variables: symbiosis, host_tax_broad, symbiont_tax_broad, mode_of_transmission_broad, endo_or_ecto, & log(host_range_link_ratio) were included (indicated by \(+\)); model weights (for the 2 models) and the sum of weights for each of the variables (from the 32 models) are included.

# creating a table
tibble(`Model (variable weight)` = c("Model1", "Model2", "Model3", "Model4", "(Sum of weights)"), 
    transmission = c(if_else(candidates_aic2$mode_of_transmission_broad == "+", "$+$", 
        "NA"), round(importance[1], 3)), host_tax = c(if_else(candidates_aic2$host_tax_broad == 
        "+", "$+$", "NA"), round(importance[2], 3)), symbiosis = c(if_else(candidates_aic2$symbiosis == 
        "+", "$+$", "NA"), round(importance[3], 3)), host_range = c(if_else(candidates_aic2$`log(host_range_link_ratio)` >= 
        0, "$+$", "NA"), round(importance[4], 3)), symbiont_tax = c(if_else(candidates_aic2$symbiont_tax_broad == 
        "+", "$+$", "NA"), round(importance[5], 3)), endo_or_ecto = c(if_else(candidates_aic2$endo_or_ecto == 
        "+", "$+$", "NA"), round(importance[6], 3)), delta_AICc = c(candidates_aic2$delta, 
        NA), Weight = c(candidates_aic2$weight, NA)) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Model (variable weight) transmission host_tax symbiosis host_range symbiont_tax endo_or_ecto delta_AICc Weight
Model1 \(+\) \(+\) \(+\) NA NA NA 0.000 0.369
Model2 \(+\) \(+\) NA NA NA NA 0.375 0.305
Model3 \(+\) \(+\) \(+\) \(+\) NA NA 1.520 0.172
Model4 \(+\) \(+\) NA \(+\) NA NA 1.749 0.154
(Sum of weights) 0.999 0.791 0.518 0.304 0.158 0.134 NA NA

Model averaging

Table 3.13

The average estimates for regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the 2 best meta-regression models. Note that mu shows the overall value at the intercept while beta represents the contrast (or slope) between two groups in the Unit column.

# getting averaged R2 and variance components not provided by the MuMIn package
average_sigma2 <- weighted.mean(x = c(model1$sigma2, model2$sigma2, model3$sigma2, 
    model4$sigma2), w = candidates_aic2$weight)
average_R2 <- weighted.mean(x = c(R2(model1)[1], R2(model2)[1], R2(model3)[1], R2(model4)[1]), 
    w = candidates_aic2$weight)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutualist)", "Microbe-Plant", 
    "Microbe-Invert", "Microbe-Vert", "host_range", "both-horizontal", "both-vertical", 
    "Mutualist-Parasite"), Estimate = mr_averaged_aic2$coefmat.full[, 1], `Lower CI [0.025]` = mr_averaged_aic2$coefmat.full[, 
    1] - mr_averaged_aic2$coefmat.full[, 2] * qnorm(0.975), `Upper CI  [0.975]` = mr_averaged_aic2$coefmat.full[, 
    1] + mr_averaged_aic2$coefmat.full[, 2] * qnorm(0.975), `V[authors]` = c(average_sigma2, 
    rep(NA, 7)), R2 = c(average_R2, rep(NA, 7))) %>% kable("html", digits = 3) %>% 
    kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutualist) 0.872 0.606 1.138 0.064 0.259
Microbe-Plant -0.415 -0.685 -0.144 NA NA
Microbe-Invert -0.311 -0.581 -0.041 NA NA
Microbe-Vert -0.278 -0.533 -0.023 NA NA
host_range -0.077 -0.215 0.060 NA NA
both-horizontal 0.166 -0.078 0.411 NA NA
both-vertical -0.040 -0.187 0.106 NA NA
Mutualist-Parasite 0.014 -0.078 0.106 NA NA

Appendix S4: Publication Bias Analysis

Here, we conducted 3 kinds of publication bias analyses: 1) contour-enhanced funnel plots (Peters et al. 2008) of residuals (Egger et al. 1997; Nakagawa & Santos 2012), 2) a type of Egger regression (Egger et al. 1997; Moreno et al. 2009), and 3) a regression-based time-lag bias test (Nakagawa & Santos 2012).

Funnel plot

A normal funnel plot assumes homogeneity (i.e., I2 = 0). Therefore, we controlled for important moderators (i.e., mode_of_transmission_broad, host_tax_broad, log(host_range_link_ratio), & symbiosis).

Residual funnel plot 1

We do not observe normal skewness in our enhanced-counter funnel plot (Supplementary Figure 5). This funnel asymmetry seems different from one caused by publication bias(Peters et al. 2008); we do not expect a “hollow” in the region with high precision or i.e. inverse standard error (2.4-4) and relative high effect sizes (Zr = 0.5-1.0). The funnel asymmetry is mainly caused by the boundary created by the number of randomizations (see the “Sensitivity Analysis” section where we deal with this skewness).

Figure 5a

# 
res_funnel_plot <- rma.mv(yi = Zr, V = VZr, mods = ~mode_of_transmission_broad + 
    host_tax_broad + log(host_range_link_ratio) + symbiosis, random = ~1 | authors, 
    data = dat)

funnel(res_funnel_plot, yaxis = "seinv", level = c(90, 95, 99), xlim = c(-3, 4), 
    ylim = c(0.9, 5.2), xlab = "Residuals (correlation)", ylab = "Precision (1/SE)", 
    shade = c("white", "gray55", "gray75"), refline = 0, legend = TRUE)

Figure 5a: A residual funnel plot from the meta-regression model with mode_of_transmission_broad, host_tax_broad, & symbiosis; ‘residual value’ is on Zr and ‘inverse standard error’ is precision 1/sqrt(VZr).

Residual funnel plot 2

Further, Egger regression analyses (see below) showed that sqrt(VZr) (sampling errors [SE] for effect sizes) accounts for much heterogeneity, so we added that to our model. The funnel asymmetry we see in Supplementary Figure 6 (if any) is much less severe than that in Supplementary Figure 5.

Figure 5b

# 
res_funnel_plot2 <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr) + mode_of_transmission_broad + 
    host_tax_broad + log(host_range_link_ratio) + symbiosis, random = ~1 | authors, 
    data = dat)

funnel(res_funnel_plot2, yaxis = "seinv", level = c(90, 95, 99), xlim = c(-3, 4), 
    ylim = c(0.9, 5.2), xlab = "Residuals (correlation)", ylab = "Precision (1/SE)", 
    shade = c("white", "gray55", "gray75"), refline = 0, legend = TRUE)

Figure 5b: A residual funnel plot from the meta-regression model with sqrt(VZr), mode_of_transmission_broad, host_tax_broad, log(host_range_link_ratio), & symbiosis; ‘residual value’ is on Zr and ‘inverse standard error’ is precision 1/sqrt(VZr).

Putting together Figure 5

# building fig 3 using patchwork

par(mfrow = c(1, 2))
funnel(res_funnel_plot, yaxis = "seinv", level = c(90, 95, 99), xlim = c(-3, 4), 
    ylim = c(0.9, 5.2), xlab = "Residuals (correlation)", ylab = "Precision (1/SE)", 
    shade = c("white", "gray55", "gray75"), refline = 0, legend = TRUE)
mtext("a", side = 3, cex = 1.5, line = 1, adj = 0)
funnel(res_funnel_plot2, yaxis = "seinv", level = c(90, 95, 99), xlim = c(-3, 4), 
    ylim = c(0.9, 5.2), xlab = "Residuals (correlation)", ylab = "Precision (1/SE)", 
    shade = c("white", "gray55", "gray75"), refline = 0, legend = TRUE)
mtext("b", side = 3, cex = 1.5, line = 1, adj = 0)

Egger’s regression

We applied Egger’s regression to test whether the funnel asymmetries we observe in our funnel plots are statistically significant or not.

Univariate Egger’s regression

The test (or sqrt(VZr)) is significant. However, as mentioned above, this is due to the boundary created by the number of randomizations; this boundary can be seen in Figure S4.1 below.

# 
egger_regression_uni <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr), random = ~1 | 
    authors, data = dat)

Table S4.1

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with sqrt(VZr).

# getting marginal R2
r2_egger_regression_uni <- R2(egger_regression_uni)

# getting estimates: name does not work for slopes
res_egger_regression_uni <- get_est(egger_regression_uni, mod = "sqrt(VZr)")

# creating a table
tibble(`Fixed effect` = c("Intercept", "sqrt(VZr)"), Estimate = c(res_egger_regression_uni$estimate), 
    `Lower CI [0.025]` = c(res_egger_regression_uni$lowerCL), `Upper CI  [0.975]` = c(res_egger_regression_uni$upperCL), 
    `V[authors]` = c(egger_regression_uni$sigma2, NA), R2 = c(r2_egger_regression_uni[1], 
        NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept 0.178 0.054 0.301 0.061 0.397
sqrt(VZr) 1.389 0.944 1.833 NA NA

Figure S4.1

pred_egger_regression_uni <- predict.rma(egger_regression_uni)

# plotting

fit_egger_regression_uni <- dat %>% mutate(ymin = pred_egger_regression_uni$ci.lb, 
    ymax = pred_egger_regression_uni$ci.ub, ymin2 = pred_egger_regression_uni$cr.lb, 
    ymax2 = pred_egger_regression_uni$cr.ub, pred = pred_egger_regression_uni$pred) %>% 
    ggplot(aes(x = sqrt(VZr), y = Zr, size = (1/VZr) + 3)) + geom_point(shape = 21, 
    fill = "grey90") + # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite sure
# why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
        colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", se = FALSE, 
    lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + xlim(0.05, 0.45) + 
    # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size =
# 0.5) +
labs(x = "sqrt(sampling variance)", y = expression(paste(italic(Zr), " (effect size)")), 
    size = expression(paste(italic(n), " (# of species pairs)"))) + guides(fill = "none", 
    colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + theme(legend.direction = "horizontal") + 
    # theme(legend.background = element_rect(fill = 'white', colour = 'black')) +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_egger_regression_uni

Figure S4.1: A bubble plot showing a predicted regression line for the continuous variable sqrt(VZr), indicating 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines), with observed effect sizes based on various sample sizes.

Multivariate Egger regression

We also conducted an Egger regression controlling other important moderators (i.e., mode_of_transmission_broad, host_tax_broad, log(host_range_link_ratio), & symbiosis). After controlling for these variables, sqrt(VZr) stays significant.

# 
egger_regression_mul <- rma.mv(yi = Zr, V = VZr, mods = ~sqrt(VZr) + mode_of_transmission_broad + 
    host_tax_broad + log(host_range_link_ratio) + symbiosis, random = ~1 | authors, 
    data = dat)

Table S4.2

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with sqrt(VZr).

# getting marginal R2
r2_egger_regression_mul <- R2(egger_regression_mul)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutualist)", "sqrt(VZr)", "both-horizontal", 
    "both-vertical", "Microbe-Plant", "Microbe-Invert", "Microbe-Vert", "host_range", 
    "Mutualist-Parasite"), Estimate = c(egger_regression_mul$b), `Lower CI [0.025]` = c(egger_regression_mul$ci.lb), 
    `Upper CI  [0.975]` = c(egger_regression_mul$ci.ub), `V[authors]` = c(egger_regression_mul$sigma2, 
        rep(NA, 8)), R2 = c(r2_egger_regression_mul[1], rep(NA, 8))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutualist) 0.420 0.123 0.717 0.044 0.583
sqrt(VZr) 1.344 0.908 1.779 NA NA
both-horizontal -0.066 -0.195 0.062 NA NA
both-vertical 0.213 -0.027 0.453 NA NA
Microbe-Plant -0.287 -0.546 -0.028 NA NA
Microbe-Invert -0.239 -0.496 0.018 NA NA
Microbe-Vert -0.146 -0.391 0.100 NA NA
host_range 0.052 -0.082 0.186 NA NA
Mutualist-Parasite -0.071 -0.237 0.096 NA NA

Figure S4.2

pred_egger_regression_mul <-predict.rma(egger_regression_mul) 

# plotting

fit_egger_regression_mul <-  dat %>% 
  filter(!is.na(mode_of_transmission_broad) & !is.na(host_tax_broad) & !is.na(symbiosis) & !is.na(host_range_link_ratio))  %>% # getting ride of NA values
  mutate(ymin = pred_egger_regression_mul$ci.lb, 
         ymax = pred_egger_regression_mul$ci.ub,
         ymin2 = pred_egger_regression_mul$cr.lb,
         ymax2 = pred_egger_regression_mul$cr.ub,
         pred = pred_egger_regression_mul$pred) %>% 
  ggplot(aes(x = sqrt(VZr), y = Zr, size = (1/VZr) + 3)) +
  geom_point(shape = 21, fill = "grey90") +
  #geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "#0072B2")  + # not quite sure why this does not work
  geom_smooth(aes(y = ymin2), method =  "loess", se = FALSE, lty =  "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymax2), method =  "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#0072B2") +
  geom_smooth(aes(y = ymin), method =  "loess", se = FALSE,lty = "dotted", lwd = 0.25, colour ="#D55E00") +
  geom_smooth(aes(y = ymax), method =  "loess", se = FALSE, lty ="dotted", lwd = 0.25, colour ="#D55E00") + 
  geom_smooth(aes(y = pred), method =  "loess", se = FALSE, lty ="dashed", lwd = 0.5, colour ="black") +  
  ylim(-1, 2) + xlim(0.05, 0.45) +
  #geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope = mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = "dashed", size = 0.5) +
  labs(x = "sqrt(sampling variance)", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), " (# of species pairs)"))) +
  guides(fill = "none", colour = "none") +
  # themses
  theme_bw() +
  theme(legend.position= c(0, 1), legend.justification = c(0, 1)) +
  theme(legend.direction="horizontal") +
  #theme(legend.background = element_rect(fill = "white", colour = "black")) +
  theme(legend.background = element_blank()) +
  theme(axis.text.y = element_text(size = 10, colour ="black", hjust = 0.5, angle = 90)) 

fit_egger_regression_mul

Figure S4.2: A bubble plot showing a predicted loess line for the continuous variable sqrt(VZr) (given the values of the other 3 variables in the model), with their 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines) with observed effect sizes based on various sample sizes. Note that the lines are not linear as these are based on multivariate predictions of the data points.

Time-lag bias

We do not find any evidence of a time-lag effect (a decline in the magnitude of the effect over time) in either the univariate or multivariate models (Figure S4.X and Figure S4.X).

Univariate time-lag bias

# 
time_lag_effect_uni <- rma.mv(yi = Zr, V = VZr, mods = ~year, random = ~1 | authors, 
    data = dat)

Table S4.3

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with year.

# getting marginal R2
r2_time_lag_effect_uni <- R2(time_lag_effect_uni)

# getting estimates: name does not work for slopes
res_time_lag_effect_uni <- get_est(time_lag_effect_uni, mod = "year")

# creating a table
tibble(`Fixed effect` = c("Intercept", "Year"), Estimate = c(res_time_lag_effect_uni$estimate), 
    `Lower CI [0.025]` = c(res_time_lag_effect_uni$lowerCL), `Upper CI  [0.975]` = c(res_time_lag_effect_uni$upperCL), 
    `V[authors]` = c(time_lag_effect_uni$sigma2, NA), R2 = c(r2_time_lag_effect_uni[1], 
        NA)) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept -3.732 -23.253 15.789 0.082 0.002
Year 0.002 -0.008 0.012 NA NA

Figure S4.3

pred_time_lag_effect_uni <- predict.rma(time_lag_effect_uni)

# plotting

fit_time_lag_effect <- dat %>% mutate(ymin = pred_time_lag_effect_uni$ci.lb, ymax = pred_time_lag_effect_uni$ci.ub, 
    ymin2 = pred_time_lag_effect_uni$cr.lb, ymax2 = pred_time_lag_effect_uni$cr.ub, 
    pred = pred_time_lag_effect_uni$pred) %>% ggplot(aes(x = year, y = Zr, size = (1/VZr) + 
    3)) + geom_point(shape = 21, fill = "grey90") + # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite sure
# why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
        colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", se = FALSE, 
    lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + xlim(1994, 2019) + 
    scale_x_continuous(breaks = c(1995, 2000, 2005, 2010, 2015, 2020)) + # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size =
# 0.5) +
labs(x = "Year", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), 
    " (# of species pairs)"))) + guides(fill = "none", colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + theme(legend.direction = "horizontal") + 
    # theme(legend.background = element_rect(fill = 'white', colour = 'black')) +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_time_lag_effect

Figure S4.3: A bubble plot showing a predicted regression line for the contenious variable year, indicating 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines), with observed effect sizes based on various sample sizes.

Multivariate time-lag bias

# 
time_lag_effect_mul <- rma.mv(yi = Zr, V = VZr, mods = ~year + mode_of_transmission_broad + 
    host_tax_broad + log(host_range_link_ratio) + symbiosis, random = ~1 | authors, 
    data = dat)

Table S4.4

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the meta-regression with year.

# getting marginal R2
r2_time_lag_effect_mul <- R2(time_lag_effect_mul)

# creating a table
tibble(`Fixed effect` = c("Intercept (both-Microbe-Mutualist)", "Year", "both-horizontal", 
    "both-vertical", "Microbe-Plant", "Microbe-Invert", "Microbe-Vert", "host_range", 
    "Mutualist-Parasite"), Estimate = c(time_lag_effect_mul$b), `Lower CI [0.025]` = c(time_lag_effect_mul$ci.lb), 
    `Upper CI  [0.975]` = c(time_lag_effect_mul$ci.ub), `V[authors]` = c(time_lag_effect_mul$sigma2, 
        rep(NA, 8)), R2 = c(r2_time_lag_effect_mul[1], rep(NA, 8))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Intercept (both-Microbe-Mutualist) 2.773 -16.237 21.783 0.066 0.259
Year -0.001 -0.010 0.009 NA NA
both-horizontal -0.073 -0.217 0.071 NA NA
both-vertical 0.154 -0.109 0.417 NA NA
Microbe-Plant -0.444 -0.725 -0.163 NA NA
Microbe-Invert -0.322 -0.601 -0.044 NA NA
Microbe-Vert -0.280 -0.545 -0.015 NA NA
host_range 0.050 -0.102 0.201 NA NA
Mutualist-Parasite -0.071 -0.253 0.110 NA NA

Figure S4.4

pred_time_lag_effect_mul <- predict.rma(time_lag_effect_mul)

# plotting
fit_time_lag_effect_mul <- dat %>% filter(!is.na(mode_of_transmission_broad) & !is.na(host_tax_broad) & 
    !is.na(symbiosis) & !is.na(host_range_link_ratio)) %>% mutate(ymin = pred_time_lag_effect_mul$ci.lb, 
    ymax = pred_time_lag_effect_mul$ci.ub, ymin2 = pred_time_lag_effect_mul$cr.lb, 
    ymax2 = pred_time_lag_effect_mul$cr.ub, pred = pred_time_lag_effect_mul$pred) %>% 
    ggplot(aes(x = year, y = Zr, size = (1/VZr) + 3)) + geom_point(shape = 21, fill = "grey90") + 
    # geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = '#0072B2') + # not quite sure
# why this does not work
geom_smooth(aes(y = ymin2), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
    colour = "#0072B2") + geom_smooth(aes(y = ymax2), method = "loess", se = FALSE, 
    lty = "dotted", lwd = 0.25, colour = "#0072B2") + geom_smooth(aes(y = ymin), 
    method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, colour = "#D55E00") + 
    geom_smooth(aes(y = ymax), method = "loess", se = FALSE, lty = "dotted", lwd = 0.25, 
        colour = "#D55E00") + geom_smooth(aes(y = pred), method = "loess", se = FALSE, 
    lty = "dashed", lwd = 0.5, colour = "black") + ylim(-1, 2) + xlim(1994, 2019) + 
    scale_x_continuous(breaks = c(1995, 2000, 2005, 2010, 2015, 2020)) + # geom_abline(intercept = mr_host_range_link_ratio$beta[[1]], slope =
# mr_host_range_link_ratio$beta[[2]], alpha = 0.7, linetype = 'dashed', size =
# 0.5) +
labs(x = "Year", y = expression(paste(italic(Zr), " (effect size)")), size = expression(paste(italic(n), 
    " (# of species pairs)"))) + guides(fill = "none", colour = "none") + # themses
theme_bw() + theme(legend.position = c(0, 1), legend.justification = c(0, 1)) + theme(legend.direction = "horizontal") + 
    # theme(legend.background = element_rect(fill = 'white', colour = 'black')) +
theme(legend.background = element_blank()) + theme(axis.text.y = element_text(size = 10, 
    colour = "black", hjust = 0.5, angle = 90))

fit_time_lag_effect_mul

Figure S4.4: A bubble plot showing a predicted loess line for the continuous variable year (given the values of the other 3 variables in the model), indicating 95% confidence regions (orange dotted lines) and 95% prediction regions (blue dotted lines) with observed effect sizes based on various sample sizes. Note that the lines are not linear as these are based on multivariate predictions of the data points.

Appendix S5: Sensitivity Analysis

The funnel plots above identified the issue of upper bounds for the effect size given a sample size (an upper limit of a p value given the number of randomizations). This boundary would influence our estimates of mean effect sizes and contrasts (i.e., comparing two groups), often making our overall conclusions too conservative. To demonstrate this, we conducted two analyses to show: 1) the number of randomizations (log(no_randomizations)) do not differ between categories in the 3 important categorical moderators (mode_of_transmission_broad, host_tax_broad, & symbiosis), and, 2) categories with high effect sizes would include “bounded” effect sizes (i.e., from p = 0.01, 0.001, or 0.0001; limit_reached) in the 3 moderators.

Sensitivity test 1: the number of randomizations

Below, we showed that none of the categories have significantly different numbers of randomizations in all mode_of_transmission_broad, host_tax_broad, & symbiosis.

The type of symbiosis: parasitism vs. mutualism

# 233 --- Yes = 74 (0.3175966%); No = 159

# symbiosis multiple intercepts
sa_random_symbiosis1 <- lmer(log(no_randomizations) ~ symbiosis - 1 + (1 | authors), 
    data = dat)
# contrast
sa_random_symbiosis2 <- lmer(log(no_randomizations) ~ symbiosis + (1 | authors), 
    data = dat)

Table S5.1

Regression coefficients (Estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2), from the regression with symbiosis on log(no_randomizations).

# getting marginal R2
r2_sa_random_symbiosis <- r2_nakagawa(sa_random_symbiosis1)

# getting estimates

res_sa_random_symbiosis <- tibble(estiamte = c(fixef(sa_random_symbiosis1), fixef(sa_random_symbiosis2)[2]))

ci_sa_random_symbiosis1 <- confint(sa_random_symbiosis1)
ci_sa_random_symbiosis2 <- confint(sa_random_symbiosis2)
res_sa_random_symbiosis %<>% mutate(lowerCL = c(ci_sa_random_symbiosis1[3:4, 1], 
    ci_sa_random_symbiosis2[4, 1]))
res_sa_random_symbiosis %<>% mutate(upperCL = c(ci_sa_random_symbiosis1[3:4, 2], 
    ci_sa_random_symbiosis2[4, 2]))

# creating a table
tibble(`Fixed effect` = c(as.character(res_symbiosis1$name), cont_gen(res_symbiosis1$name)), 
    Estimate = res_sa_random_symbiosis$estiamte, `Lower CI [0.025]` = res_sa_random_symbiosis$lowerCL, 
    `Upper CI  [0.975]` = res_sa_random_symbiosis$upperCL, `V[authors]` = c(attr(VarCorr(sa_random_symbiosis1)$author, 
        "stddev")^2, rep(NA, 2)), `V[residuals]` = c(attr(VarCorr(sa_random_symbiosis1), 
        "sc")^2, rep(NA, 2)), R2 = c(r2_sa_random_symbiosis$R2_marginal, rep(NA, 
        2))) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
Mutualist 7.696 7.286 8.106 2.931 0.352 0.004
Parasite 7.619 7.314 7.924 NA NA NA
Mutualist-Parasite -0.077 -0.544 0.389 NA NA NA

The effect of host taxa

# host_tax_broad mutiple intercepts
sa_random_host_tax_broad1 <- lmer(log(no_randomizations) ~ host_tax_broad - 1 + (1 | 
    authors), data = dat)
# contrast 1
sa_random_host_tax_broad2 <- lmer(log(no_randomizations) ~ host_tax_broad + (1 | 
    authors), data = dat)
# contrast 2
sa_random_host_tax_broad3 <- lmer(log(no_randomizations) ~ relevel(host_tax_broad, 
    ref = "Plant") + (1 | authors), data = dat)

# contrast 3
sa_random_host_tax_broad4 <- lmer(log(no_randomizations) ~ relevel(host_tax_broad, 
    ref = "Invert") + (1 | authors), data = dat)

Table S5.2

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the regression with host_tax_broad on log(no_randomizations).

# getting marginal R2
r2_sa_random_host_tax_broad <- r2_nakagawa(sa_random_host_tax_broad1)

# getting estimates
res_sa_random_host_tax_broad <- tibble(estiamte = c(fixef(sa_random_host_tax_broad1), 
                                                    fixef(sa_random_host_tax_broad2)[2:4],
                                                    fixef(sa_random_host_tax_broad3)[3:4],
                                                    fixef(sa_random_host_tax_broad4)[4])) 
  
ci_sa_random_host_tax_broad1<-confint(sa_random_host_tax_broad1)
ci_sa_random_host_tax_broad2<-confint(sa_random_host_tax_broad2)
ci_sa_random_host_tax_broad3<-confint(sa_random_host_tax_broad3)
ci_sa_random_host_tax_broad4<-confint(sa_random_host_tax_broad4)
res_sa_random_host_tax_broad %<>% mutate(lowerCL = c(ci_sa_random_host_tax_broad1[3:6,1], 
                                                ci_sa_random_host_tax_broad2[4:6,1],
                                                ci_sa_random_host_tax_broad3[5:6,1],
                                                ci_sa_random_host_tax_broad4[6,1]))
res_sa_random_host_tax_broad %<>% mutate(upperCL = c(ci_sa_random_host_tax_broad1[3:6,2], 
                                                ci_sa_random_host_tax_broad2[4:6,2],
                                                ci_sa_random_host_tax_broad3[5:6,2],
                                                ci_sa_random_host_tax_broad4[6,2]))
# creating a table
tibble(
  `Fixed effect` =  c(as.character(res_symbiont_tax_broad1$name), cont_gen(res_symbiont_tax_broad1$name)), # done
  Estimate = res_sa_random_host_tax_broad$estiamte,
  `Lower CI [0.025]` = res_sa_random_host_tax_broad$lowerCL,
  `Upper CI  [0.975]` = res_sa_random_host_tax_broad$upperCL,
  `V[authors]` = c(attr(VarCorr(sa_random_host_tax_broad1)$author,"stddev")^2,  rep(NA, 9)),
  `V[residuals]` =c(attr(VarCorr(sa_random_host_tax_broad1),"sc")^2, rep(NA, 9)),
  `R2` = c(r2_sa_random_host_tax_broad$R2_marginal, rep(NA, 9))) %>% kable("html", digits = 3) %>%
  kable_styling("striped", position = "left") 
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
Microbe 8.223 7.279 9.168 2.937 0.35 0.071
Plant 7.466 6.856 8.076 NA NA NA
Invert 7.650 7.167 8.134 NA NA NA
Vert 7.634 7.265 8.003 NA NA NA
Microbe-Plant -0.757 -1.882 0.367 NA NA NA
Microbe-Invert -0.573 -1.634 0.488 NA NA NA
Microbe-Vert -0.589 -1.603 0.425 NA NA NA
Plant-Invert 0.184 -0.594 0.962 NA NA NA
Plant-Vert 0.168 -0.545 0.881 NA NA NA
Invert-Vert -0.016 -0.599 0.566 NA NA NA

The effect of the mode of transmission

# mode_of_transmission_broad

sa_random_mode_of_transmission_broad1 <- lmer(log(no_randomizations) ~ mode_of_transmission_broad - 
    1 + (1 | authors), data = dat)


# contrast 1
sa_random_mode_of_transmission_broad2 <- lmer(log(no_randomizations) ~ mode_of_transmission_broad + 
    (1 | authors), data = dat)

# contrast 2
sa_random_mode_of_transmission_broad3 <- lmer(log(no_randomizations) ~ relevel(mode_of_transmission_broad, 
    ref = "vertical") + (1 | authors), data = dat)

Table S5.3

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the regression with mode_of_transmission_broad on log(no_randomizations).

# getting marginal R2
r2_sa_random_mode_of_transmission_broad <- r2_nakagawa(sa_random_mode_of_transmission_broad1)

# getting estimates
res_sa_random_mode_of_transmission_broad <- tibble(estiamte = c(fixef(sa_random_mode_of_transmission_broad1), 
    fixef(sa_random_mode_of_transmission_broad2)[2:3], fixef(sa_random_mode_of_transmission_broad3)[3]))

ci_sa_random_mode_of_transmission_broad1 <- confint(sa_random_mode_of_transmission_broad1)
ci_sa_random_mode_of_transmission_broad2 <- confint(sa_random_mode_of_transmission_broad2)
ci_sa_random_mode_of_transmission_broad3 <- confint(sa_random_mode_of_transmission_broad3)
res_sa_random_mode_of_transmission_broad %<>% mutate(lowerCL = c(ci_sa_random_mode_of_transmission_broad1[3:5, 
    1], ci_sa_random_mode_of_transmission_broad2[4:5, 1], ci_sa_random_mode_of_transmission_broad3[5, 
    1]))
res_sa_random_mode_of_transmission_broad %<>% mutate(upperCL = c(ci_sa_random_mode_of_transmission_broad1[3:5, 
    2], ci_sa_random_mode_of_transmission_broad2[4:5, 2], ci_sa_random_mode_of_transmission_broad3[5, 
    2]))
# creating a table
tibble(`Fixed effect` = c(as.character(res_mode_of_transmission_broad1$name), cont_gen(res_mode_of_transmission_broad1$name)), 
    Estimate = res_sa_random_mode_of_transmission_broad$estiamte, `Lower CI [0.025]` = res_sa_random_mode_of_transmission_broad$lowerCL, 
    `Upper CI  [0.975]` = res_sa_random_mode_of_transmission_broad$upperCL, `V[authors]` = c(attr(VarCorr(sa_random_mode_of_transmission_broad1)$author, 
        "stddev")^2, rep(NA, 5)), `V[residuals]` = c(attr(VarCorr(sa_random_mode_of_transmission_broad1), 
        "sc")^2, rep(NA, 5)), R2 = c(r2_sa_random_mode_of_transmission_broad$R2_marginal, 
        rep(NA, 5))) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] V[residuals] R2
both 7.535 6.978 8.091 2.913 0.363 0.12
horizontal 7.515 7.164 7.866 NA NA NA
vertical 8.089 7.509 8.668 NA NA NA
both-horizontal -0.020 -0.678 0.638 NA NA NA
both-vertical 0.554 -0.250 1.357 NA NA NA
horizontal-vertical -0.574 -1.251 0.104 NA NA NA

Sensitivity test 2: reaching the limits

Below, we show that categories with higher effect sizes were more likely to have “bounded” effect sizes (limit_reached) in all mode_of_transmission_broad, host_tax_broad, & symbiosis. This indicates that the higher the estimate of mean effect size is, the more underestimated the mean effect size is. This is true for differences between two categories; the larger the difference between the two, the more underestimated the difference is.

The type of symbiosis: parasitism vs. mutualism

Table S5.4

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the regression with symbiosis on limit_reached (compare the effect estimates in Table S3.1 with the corresponding values in this table below; their ranking in estimation should usually match).

# symbiosis
sa_limit_symbiosis1 <- glmer(limit_reached ~ symbiosis - 1 + (1 | authors), family = "binomial", 
    data = dat)

# getting marginal R2
r2_sa_limit_symbiosis <- r2_nakagawa(sa_limit_symbiosis1)

# getting estimates
res_sa_limit_symbiosis <- tibble(estiamte = fixef(sa_limit_symbiosis1))

res_sa_limit_symbiosis %<>% mutate(lowerCL = (tidy(sa_limit_symbiosis1)$estimate[-3] - 
    tidy(sa_limit_symbiosis1)$std.error[-3] * qnorm(0.975)))
res_sa_limit_symbiosis %<>% mutate(upperCL = (tidy(sa_limit_symbiosis1)$estimate[-3] + 
    tidy(sa_limit_symbiosis1)$std.error[-3] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_symbiosis1$name), Estimate = res_sa_limit_symbiosis$estiamte, 
    `Lower CI [0.025]` = res_sa_limit_symbiosis$lowerCL, `Upper CI  [0.975]` = res_sa_limit_symbiosis$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_limit_symbiosis1)$author, "stddev")^2, rep(NA, 
        1)), R2 = c(r2_sa_limit_symbiosis$R2_marginal, rep(NA, 1))) %>% kable("html", 
    digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Mutualist -0.401 -1.074 0.272 1.657 0.051
Parasite -1.309 -2.015 -0.603 NA NA
# t_symbiosis

Table S3.1* (for comparision)

In both tables, mutualist has higher estimates (i.e, mutualist rearched the ceiling more often)

t_symbiosis %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Mutualist Zr (mu) 0.631 0.534 0.727 0.078 0.054
Parasite Zr (mu) 0.487 0.419 0.554 NA NA
Mutualist r (mu) 0.559 0.488 0.621 NA NA
Parasite r (mu) 0.451 0.396 0.503 NA NA
Mutualist-Parasite Zr (beta) -0.144 -0.260 -0.028 NA NA

The effect of host taxa

Table S5.5

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the regression with host_tax_broad on limit_reached (compare the effect estimates in Table S3.2 with the corresponding values in this table below; their ranking in estimation should usually match).

# host_tax_broad
sa_limit_host_tax_broad1 <- glmer(limit_reached ~ host_tax_broad - 1 + (1 | authors), 
    family = "binomial", data = dat)

# getting marginal R2
r2_sa_limit_host_tax_broad <- r2_nakagawa(sa_limit_host_tax_broad1)

# getting estimates
res_sa_limit_host_tax_broad <- tibble(estiamte = fixef(sa_limit_host_tax_broad1))

res_sa_limit_host_tax_broad %<>% mutate(lowerCL = (tidy(sa_limit_host_tax_broad1)$estimate[-5] - 
    tidy(sa_limit_host_tax_broad1)$std.error[-5] * qnorm(0.975)))
res_sa_limit_host_tax_broad %<>% mutate(upperCL = (tidy(sa_limit_host_tax_broad1)$estimate[-5] + 
    tidy(sa_limit_host_tax_broad1)$std.error[-5] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_symbiont_tax_broad1$name), Estimate = res_sa_limit_host_tax_broad$estiamte, 
    `Lower CI [0.025]` = res_sa_limit_host_tax_broad$lowerCL, `Upper CI  [0.975]` = res_sa_limit_host_tax_broad$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_limit_host_tax_broad1)$author, "stddev")^2, 
        rep(NA, 3)), R2 = c(r2_sa_limit_host_tax_broad$R2_marginal, rep(NA, 3))) %>% 
    kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe -1.211 -2.737 0.316 1.358 0.035
Plant -1.574 -2.571 -0.578 NA NA
Invert -0.579 -1.308 0.150 NA NA
Vert -0.937 -1.588 -0.286 NA NA
# t_host_tax

Table S3.2* (for comparision)

t_host_tax %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
Microbe Zr (mu) 0.883 0.639 1.126 0.077 0.162
Plant Zr (mu) 0.377 0.256 0.498 NA NA
Invert Zr (mu) 0.629 0.522 0.736 NA NA
Vert Zr (mu) 0.515 0.435 0.595 NA NA
Microbe r (mu) 0.708 0.564 0.810 NA NA
Plant r (mu) 0.360 0.250 0.460 NA NA
Invert r (mu) 0.557 0.479 0.627 NA NA
Vert r (mu) 0.474 0.410 0.534 NA NA
Microbe-Plant Zr (beta) -0.506 -0.778 -0.234 NA NA
Microbe-Invert Zr (beta) -0.254 -0.519 0.012 NA NA
Microbe-Vert Zr (beta) -0.367 -0.624 -0.111 NA NA
Plant-Invert Zr (beta) 0.252 0.091 0.414 NA NA
Plant-Vert Zr (beta) 0.139 -0.006 0.284 NA NA
Invert-Vert Zr (beta) -0.114 -0.244 0.017 NA NA

The effect of the mode of transmission

Table S5.6

Regression coefficients (estimate), 95% confidence intervals (CIs), variance components (V) and variance explained, R2[marginal] (R2) from the regression with mode_of_transmission_broad on limit_reached (compare the effect estimates in Table S3.7 with the corresponding values in this table below; their ranking in estimation should usually match).

# mode_of_transmission_broad
sa_limit_mode_of_transmission_broad1 <- glmer(limit_reached ~ mode_of_transmission_broad - 
    1 + (1 | authors), family = "binomial", data = dat)

# getting marginal R2
r2_sa_limit_mode_of_transmission_broad <- r2_nakagawa(sa_limit_mode_of_transmission_broad1)

# getting estimates
res_sa_limit_mode_of_transmission_broad <- tibble(estiamte = fixef(sa_limit_mode_of_transmission_broad1))

res_sa_limit_mode_of_transmission_broad %<>% mutate(lowerCL = (tidy(sa_limit_mode_of_transmission_broad1)$estimate[-4] - 
    tidy(sa_limit_mode_of_transmission_broad1)$std.error[-4] * qnorm(0.975)))
res_sa_limit_mode_of_transmission_broad %<>% mutate(upperCL = (tidy(sa_limit_mode_of_transmission_broad1)$estimate[-4] + 
    tidy(sa_limit_mode_of_transmission_broad1)$std.error[-4] * qnorm(0.975)))
# creating a table
tibble(`Fixed effect` = as.character(res_mode_of_transmission_broad1$name), Estimate = res_sa_limit_mode_of_transmission_broad$estiamte, 
    `Lower CI [0.025]` = res_sa_limit_mode_of_transmission_broad$lowerCL, `Upper CI  [0.975]` = res_sa_limit_mode_of_transmission_broad$upperCL, 
    `V[authors]` = c(attr(VarCorr(sa_limit_mode_of_transmission_broad1)$author, "stddev")^2, 
        rep(NA, 2)), R2 = c(r2_sa_limit_mode_of_transmission_broad$R2_marginal, rep(NA, 
        2))) %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
both -0.928 -1.809 -0.046 1.427 0.078
horizontal -1.326 -2.031 -0.621 NA NA
vertical 0.060 -0.750 0.869 NA NA
# t_transmission

Table S3.7* (for comparision)

t_transmission %>% kable("html", digits = 3) %>% kable_styling("striped", position = "left")
Fixed effect Unit Estimate Lower CI [0.025] Upper CI [0.975] V[authors] R2
both Zr (mu) 0.578 0.463 0.693 0.061 0.187
horizontal Zr (mu) 0.446 0.378 0.515 NA NA
vertical Zr (mu) 0.751 0.634 0.868 NA NA
both r (mu) 0.521 0.432 0.600 NA NA
horizontal r (mu) 0.419 0.361 0.474 NA NA
vertical r (mu) 0.636 0.561 0.701 NA NA
both-horizontal Zr (beta) -0.131 -0.265 0.002 NA NA
both-vertical Zr (beta) 0.174 0.009 0.338 NA NA
horizontal-vertical Zr (beta) -0.305 -0.441 -0.169 NA NA

Acknowledgements

Many coding materials have been borrowed from these papers (Cally et al. 2019; O’Dea et al. 2019). We thank Losia Lagisz for preparing small icons and cartoons used in the figures.

R Session Information

# pander for making it look nicer
sessionInfo() %>% pander()

R version 4.0.3 (2020-10-10)

Platform: x86_64-apple-darwin17.0 (64-bit)

locale: en_AU.UTF-8||en_AU.UTF-8||en_AU.UTF-8||C||en_AU.UTF-8||en_AU.UTF-8

attached base packages: grid, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: here(v.1.0.1), patchwork(v.1.1.1), png(v.0.1-7), performance(v.0.6.1), broom.mixed(v.0.2.6), lme4(v.1.1-26), MuMIn(v.1.43.17), plotly(v.4.9.3), ggbeeswarm(v.0.6.0), MCMCglmm(v.2.30), ape(v.5.4-1), coda(v.0.19-4), metafor(v.2.5-74), Matrix(v.1.3-2), pander(v.0.6.3), magrittr(v.2.0.1), gridExtra(v.2.3), kableExtra(v.1.3.1), forcats(v.0.5.1), stringr(v.1.4.0), dplyr(v.1.0.3), purrr(v.0.3.4), readr(v.1.4.0), tidyr(v.1.1.2), tibble(v.3.0.5), ggplot2(v.3.3.3) and tidyverse(v.1.3.0)

loaded via a namespace (and not attached): nlme(v.3.1-151), fs(v.1.5.0), lubridate(v.1.7.9.2), insight(v.0.12.0), webshot(v.0.5.2), httr(v.1.4.2), rprojroot(v.2.0.2), tensorA(v.0.36.2), tools(v.4.0.3), TMB(v.1.7.18), backports(v.1.2.1), R6(v.2.5.0), vipor(v.0.4.5), mgcv(v.1.8-33), DBI(v.1.1.1), lazyeval(v.0.2.2), colorspace(v.2.0-0), withr(v.2.4.1), tidyselect(v.1.1.0), compiler(v.4.0.3), cli(v.2.2.0), rvest(v.0.3.6), formatR(v.1.7), pacman(v.0.5.1), xml2(v.1.3.2), labeling(v.0.4.2), bayestestR(v.0.8.2), scales(v.1.1.1), digest(v.0.6.27), minqa(v.1.2.4), rmarkdown(v.2.6), pkgconfig(v.2.0.3), htmltools(v.0.5.1.1), highr(v.0.8), dbplyr(v.2.0.0), htmlwidgets(v.1.5.3), rlang(v.0.4.10), readxl(v.1.3.1), rstudioapi(v.0.13), farver(v.2.0.3), generics(v.0.1.0), jsonlite(v.1.7.2), Rcpp(v.1.0.6), munsell(v.0.5.0), fansi(v.0.4.2), lifecycle(v.0.2.0), stringi(v.1.5.3), yaml(v.2.2.1), mathjaxr(v.1.0-1), MASS(v.7.3-53), plyr(v.1.8.6), parallel(v.4.0.3), crayon(v.1.3.4), lattice(v.0.20-41), haven(v.2.3.1), splines(v.4.0.3), hms(v.1.0.0), knitr(v.1.31), pillar(v.1.4.7), boot(v.1.3-26), cubature(v.2.0.4.1), corpcor(v.1.6.9), codetools(v.0.2-18), reshape2(v.1.4.4), stats4(v.4.0.3), reprex(v.1.0.0), glue(v.1.4.2), evaluate(v.0.14), data.table(v.1.13.6), modelr(v.0.1.8), vctrs(v.0.3.6), nloptr(v.1.2.2.2), cellranger(v.1.1.0), gtable(v.0.3.0), assertthat(v.0.2.1), xfun(v.0.20), broom(v.0.7.3), viridisLite(v.0.3.0), beeswarm(v.0.2.3), statmod(v.1.4.35) and ellipsis(v.0.3.1)

References

Barton, K. (2009). MuMIn: Multi-model inference. http://r-forge. r-project. org/projects/mumin/.
Cally, J.G., Stuart-Fox, D. & Holman, L. (2019). Meta-analytic evidence that sexual selection improves population fitness. Nature communications, 10, 2017.
Egger, M., Smith, G.D., Schneider, M. & Minder, C. (1997). Bias in meta-analysis detected by a simple, graphical test. Bmj, 315, 629–634.
Higgins, J.P., Thompson, S.G., Deeks, J.J. & Altman, D.G. (2003). Measuring inconsistency in meta-analyses. Bmj, 327, 557–560.
Knapp, G. & Hartung, J. (2003). Improved tests for a random effects meta-regression with a single covariate. Statistics in medicine, 22, 2693–2710.
Legendre, P., Desdevises, Y. & Bazin, E. (2002). A statistical test for host–parasite coevolution. Systematic biology, 51, 217–234.
Moreno, S.G., Sutton, A.J., Ades, A., Stanley, T.D., Abrams, K.R., Peters, J.L., et al. (2009). Assessment of regression-based methods to adjust for publication bias through a comprehensive simulation study. BMC medical research methodology, 9, 2.
Nakagawa, S. & Santos, E.S. (2012). Methodological issues and advances in biological meta-analysis. Evolutionary Ecology, 26, 1253–1274.
Nakagawa, S. & Schielzeth, H. (2013). A general and simple method for obtaining R2 from generalized linear mixed-effects models. Methods in ecology and evolution, 4, 133–142.
O’Dea, R.E., Lagisz, M., Hendry, A.P. & Nakagawa, S. (2019). Developmental temperature affects phenotypic means and variability: A meta-analysis of fish data. Fish and Fisheries, 20, 1005–1022.
Page, R.D. (1994). Parallel phylogenies: Reconstructing the history of host-parasite assemblages. Cladistics, 10, 155–173.
Peters, J.L., Sutton, A.J., Jones, D.R., Abrams, K.R. & Rushton, L. (2008). Contour-enhanced meta-analysis funnel plots help distinguish publication bias from other causes of asymmetry. Journal of clinical epidemiology, 61, 991–996.
Rosenthal, R. & Rubin, D.B. (2003). Requivalent: A simple effect size indicator. Psychological methods, 8, 492.
Senior, A.M., Grueber, C.E., Kamiya, T., Lagisz, M., O’dwyer, K., Santos, E.S., et al. (2016). Heterogeneity in ecological and evolutionary meta-analyses: Its magnitude and implications. Ecology, 97, 3293–3299.
Viechtbauer, W. (2010). Conducting meta-analyses in R with the metafor package. Journal of Statistical Software, 36, 1–48.
LS0tCnRpdGxlOiAiQSBCcm9hZHNjYWxlIFRlc3Qgb2YgSG9zdC1TeW1iaW9udCBDb3BoeWxvZ2VueSBSZXZlYWxzIEtleSBEcml2ZXJzIG9mIFBoeWxvZ2VuZXRpYyBDb25ncnVlbmNlIgphdXRob3I6ICJBbGV4YW5kZXIgSGF5d2FyZCwgUm9iZXJ0IFBvdWxpbiAmIFNoaW5pY2hpIE5ha2FnYXdhIgpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiAlWScpYCIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGRlcHRoOiA0CiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0aGVtZTogIGNvc21vICMg4oCcZGVmYXVsdOKAnSwg4oCcY2VydWxlYW7igJ0sIOKAnGpvdXJuYWzigJ0sIOKAnGZsYXRseeKAnSwg4oCcZGFya2x54oCdLCDigJxyZWFkYWJsZeKAnSwg4oCcc3BhY2VsYWLigJ0sIOKAnHVuaXRlZOKAnSwg4oCcY29zbW/igJ0sIOKAnGx1bWVu4oCdLCDigJxwYXBlcuKAnSwg4oCcc2FuZHN0b25l4oCdLCDigJxzaW1wbGV44oCdLCDigJx5ZXRp4oCdCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19kZXB0aDogNAogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCnN1YnRpdGxlOiBTdXBwbGVtZW50YXJ5IE1hdGVyaWFsCmJpYmxpb2dyYXBoeTogcmVmZXJlbmNlcy5iaWIKI2JpYmxpby1zdHlsZTogImFwYWxpa2UiCmNzbDogZWNvbF9sZXR0LmNzbApsaW5rLWNpdGF0aW9uczogeWVzCiNhbHdheXNfYWxsb3dfaHRtbDogdHJ1ZQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlID0gRkFMU0V9CiNrbml0ZXIgc2VldHRpbmcKa25pdHI6Om9wdHNfY2h1bmskc2V0KAptZXNzYWdlID0gRkFMU0UsCndhcm5pbmcgPSBGQUxTRSwgIyBubyB3YXJuaW5ncwpjYWNoZSA9IFRSVUUsIyBDYWNoZWluZyB0byBzYXZlIHRpbWUgd2hlbiBrbml0aW5nCnRpZHkgPSBUUlVFCiNmaWcud2lkdGggPSA5CikKCiMgY2xlYXJuaW5nIHVwCnJtKGxpc3Q9bHMoKSkKYGBgCgojIyBTZXR1cHMKCiMjIyBMb2FkaW5nIHBhY2thZ2VzIGFuZCBjdXN0b20gZnVuY3Rpb25zCgpgYGB7cn0KIyBsb2FkaW5nIHBhY2thZ2VzCiMgZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJ0aG9tYXNwODUvcGF0Y2h3b3JrIikKcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlLCAjIHRpZHkgZmFtaWx5IGFuZCByZWxhdGVkIHBhY2FrZ2VzIGJlbG93CiAgICAgICAgICAgICAgIGthYmxlRXh0cmEsIAogICAgICAgICAgICAgICBncmlkRXh0cmEsICMgbWF5IG5vdCB1c2UgdGhpcwogICAgICAgICAgICAgICBwdXJyciwKICAgICAgICAgICAgICAgbWFncml0dHIsICMgZXh0ZW5kaW5nIHBpcGluZwogICAgICAgICAgICAgICBwYW5kZXIsICAgIyBuaWNlIHRhYmxlcwogICAgICAgICAgICAgICBtZXRhZm9yLCAgIyBwYWNrYWdlIGZvciBtZXRhLWFuYWx5c2lzCiAgICAgICAgICAgICAgIE1DTUNnbG1tLCAgIyBCYXllaXNhbiBtaXhlZCBtb2RlbCBwYWNrYWdlCiAgICAgICAgICAgICAgIGdnYmVlc3dhcm0sICMgbWFraW5nIGJlZS1zd2FybSBwbG90cyBwb3NzaWJsZQogICAgICAgICAgICAgICBwbG90bHksICAgICAjIGludGVyYWN0aXZlIHBsb3RzIHVzaW5nIGdncGxvdDIKICAgICAgICAgICAgICAgTXVNSW4sICAjIG11bHRpLW1vZGVsIGluZmVyZW5jZQogICAgICAgICAgICAgICBsbWU0LCAgICMgbG1tICYgZ2xtbSAobW9kZWxzKQogICAgICAgICAgICAgICBicm9vbS5taXhlZCwgIyBnZXR0aW5nIGVzdGltYXRlcyBmcm9tIGxtZXIgKyBnbG1lciBvYmplY3RzCiAgICAgICAgICAgICAgIHBlcmZvcm1hbmNlLCAjIGdldHRpbmcgUjIgZnJvbSBsbWVyICsgZ2xtZXIgb2JqZWN0cwogICAgICAgICAgICAgICBwbmcsICAgICAgICAgIyByZWFkaW5nIHBuZyBmaWxlcwogICAgICAgICAgICAgICBncmlkLCAgICAgICAgIyBncmFwaGljIGxheW91dCBtYW5pcHVsYXRpb24KICAgICAgICAgICAgICAgcGF0Y2h3b3JrLCAgICMgcHV0dGluZyBnZ3Bsb3RzIHRvZ2V0aGVyIC0geW91IG5lZWQgdG8gaW5zdGFsbCB2aWEgZGV2dG9vbAogICAgICAgICAgICAgICBoZXJlICAgICAgICAgIyBtYWtpbmcgcmVhZGluZyBmaWxlcyBlYXN5CiAgICAgICAgICAgICAgICNsbWVyVGVzdCwgICAjIG1vcmUgZnVuY3Rpb25zIGZvciBsbWU0CiAgICAgICAgICAgICAgICNtaSwgICAgICAjIG1pc3NpbmcgZGF0YSBhbmFseXNpcwogICAgICAgICAgICAgICAjYmV0YXJlZyAgICMgZGVwZW5kZW5jZSBvZiB0aGUgYWJvdmUKKQpgYGAKCiMjIyMgQ3VzdG9tIGZ1bmN0aW9ucwoKV2UgaGF2ZSA1IGN1c3RvbSBmdW5jdGlvbnMgbmFtZWQgOiBgcF90b19acigpYCxgSTIoKWAsIGBSMigpYCwgYGdldF9lc3QoKWAsIGBnZXRfcHJlZCgpYCwgYW5kIGBjb250X2dlbigpYCwgYWxsIG9mIHdoaWNoIGFyZSB1c2VkIGxhdGVyIChzZWUgYmVsb3cgZm9yIHRoZWlyIGZ1bmN0aW9uYWxpdHkpIGFuZCB0aGUgY29kZSBpcyBpbmNsdWRlZCBoZXJlLiAKCmBgYHtyfQojIGNvdXN0bSBmdW5jdGlvbnMKCiMnIFRpdGxlOiBnZXR0aW5nIFpyIGFuZCBpdHMgc2FtcGxpbmcgdmFyaWFuY2UgZnJvbSBwIHZhbHVlIAojJwojJyBAcGFyYW0gZGF0YTogZGF0YSBmcmFtZSAKIycgQHBhcmFtIHB2YWw6IHAgdmFsdWUKIycgQHBhcmFtIE46IHNhbXBsZSBzaXplIChOOiB0aGUgbnVtYmVyIG9mIHNwZWNpZXMgKSBhbmQgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSBkZiA9IE4gLSAyCiMnCiMnIEByZXR1cm4KIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKcF90b19aciA8LSBmdW5jdGlvbihkYXRhLCBwdmFsLCBOKSB7CiAgCiAgIyB0dXJuaW5nIHRoZW0gaW50byBzdHJpbmdzCiAgcHZhbCA8LSBkYXRhW1tkZXBhcnNlKHN1YnN0aXR1dGUocHZhbCkpXV0KICBOIDwtIGRhdGFbW2RlcGFyc2Uoc3Vic3RpdHV0ZShOKSldXQogIAogICMgZ2V0dGluZyB0IHZhbHVlcyAKICB0dmFsPC0gLXF0KHB2YWwsIE4gLSAyKSAKICBydmFsIDwtIHR2YWwgLyBzcXJ0KCh0dmFsXjIpICsgKE4gLSAyKSkKICAKICAjIGRlZmluZSBaciBmdW5jdGlvbgogICMgWnIgPC0gMC41Kihsb2coMSArIHJ2YWwpIC0gbG9nKDEgLSBydmFsKSk7IHRoZSBzYW1lIGFzIGJlbG93CiAgIyByIDwtdGFuaChacikgIyB0dXJuaW5nIFpyIHRvIHIKICBaciA8LSBhdGFuaChydmFsKQogIAogICMgZ2V0dGluZyBWYXIoWnIpCiAgVlpyIDwtIDEgLyAoTiAtIDMpCiAgCiAgIyBwdXR0aW5nIGFsbCB0b2dldGhlcgogIFpycyA8LSB0aWJibGUocnZhbCwgWnIsIFZacikKICBkYXRhIDwtIGJpbmRfY29scyhkYXRhLCBacnMpCn0KCiMgY292ZXJ0aW5nIGJhY2sgWnIgdG8gcgojIEp1c3QgdXNlICJwc3ljaCIgcGFjYWtnZSAtIGZpc2hlcnoycih6KSAtIDxodHRwOi8vcGVyc29uYWxpdHktcHJvamVjdC5vcmcvci9wc3ljaC9oZWxwL2Zpc2hlcnouaHRtbD4KIyBvciB0aGlzIHdpbGwgZG8gOiByIHRvIFpyIGlzIHRhbmgocikhIQoKIyBGdW5jdGlvbnMgZm9yIHByb2Nlc3NpbmcKCgojIEdlbmVyYWwgbW9kZWxpbmcgZnVuY3Rpb25zIAojIEZ1bmN0aW9ucyBmb3IgSTIKCiMnIFRpdGxlIEZ1bmN0aW9uIHRvIG9idGFpbiB0b3RhbCBhbmQgc2VwYXJhdGUgSTIgZnJvbSBtdWx0aWxldmVsLW1ldGEtYW5hbHl0aWMgbW9kZWwKIycKIycgQHBhcmFtIG1vZGVsIAojJyBAcGFyYW0gbWV0aG9kIAojJwojJyBAcmV0dXJuCiMnIEBleHBvcnQKIycKIycgQGV4YW1wbGVzCkkyIDwtIGZ1bmN0aW9uKG1vZGVsLCBtZXRob2QgPSBjKCJXb2xmZ2FuZyIsICJTaGluaWNoaSIpKXsKICAKICAjIyBldmFsdWF0ZSBjaG9pY2VzCiAgbWV0aG9kIDwtIG1hdGNoLmFyZyhtZXRob2QpCiAgCiAgIyBXb2xmZ2FuZydzIG1ldGhvZAogIGlmKG1ldGhvZCA9PSAiV29sZmdhbmciKXsKICAgIFcgPC0gc29sdmUobW9kZWwkVikgCiAgICBYIDwtIG1vZGVsLm1hdHJpeChtb2RlbCkKICAgIFAgPC0gVyAtIFcgJSolIFggJSolIHNvbHZlKHQoWCkgJSolIFcgJSolIFgpICUqJSB0KFgpICUqJSBXCiAgICBJMl90b3RhbCA8LSBzdW0obW9kZWwkc2lnbWEyKSAvIChzdW0obW9kZWwkc2lnbWEyKSArIChtb2RlbCRrIC0gbW9kZWwkcCkgLyBzdW0oZGlhZyhQKSkpCiAgICBJMl9lYWNoICA8LSBtb2RlbCRzaWdtYTIgLyAoc3VtKG1vZGVsJHNpZ21hMikgKyAobW9kZWwkayAtIG1vZGVsJHApIC8gc3VtKGRpYWcoUCkpKQogICAgbmFtZXMoSTJfZWFjaCkgPSBwYXN0ZTAoIkkyXyIsIG1vZGVsJHMubmFtZXMpCiAgICAKICAgICMgcHV0dGluZyBhbGwgdG9nZXRoZXIKICAgIEkycyA8LSBjKEkyX3RvdGFsID0gSTJfdG90YWwsIEkyX2VhY2gpCiAgICAKICAgICMgb3IgbXkgd2F5CiAgfSBlbHNlIHsKICAgICMgc2lnbWEyX3YgPSB0eXBpY2FsIHNhbXBsaW5nIGVycm9yIHZhcmlhbmNlCiAgICBzaWdtYTJfdiA8LSBzdW0oMS9tb2RlbCR2aSkgKiAobW9kZWwkay0xKSAvIChzdW0oMS9tb2RlbCR2aSleMiAtIHN1bSgoMS9tb2RlbCR2aSleMikpIAogICAgSTJfdG90YWwgPC0gc3VtKG1vZGVsJHNpZ21hMikgLyAoc3VtKG1vZGVsJHNpZ21hMikgKyBzaWdtYTJfdikgI3NeMl90ID0gdG90YWwgdmFyaWFuY2UKICAgIEkyX2VhY2ggIDwtIG1vZGVsJHNpZ21hMiAvIChzdW0obW9kZWwkc2lnbWEyKSArIHNpZ21hMl92KQogICAgbmFtZXMoSTJfZWFjaCkgPSBwYXN0ZTAoIkkyXyIsIG1vZGVsJHMubmFtZXMpCiAgICAKICAgICMgcHV0dGluZyBhbGwgdG9nZXRoZXIKICAgIEkycyA8LSBjKEkyX3RvdGFsID0gSTJfdG90YWwsIEkyX2VhY2gpCiAgfQogIHJldHVybihJMnMpCn0KCiMgdGVzdCA8LSBkYXRhc2V0JGZpdDQuMVtbM11dCiMgSTIodGVzdCwgbWV0aG9kID0gIldvbGZnYW5nIikKIyBJMih0ZXN0LCBtZXRob2QgPSAiU2hpbmljaGkiKQoKCiMnIFRpdGxlOiBSMiBiYXNlZCBvbiBOYWthZ2F3YSAmIFNjaGllbHpldGggMjAxMwojJwojJyBAcGFyYW0gbW9kZWwgCiMnCiMnIEByZXR1cm4KIycgQGV4cG9ydAojJwojJyBAZXhhbXBsZXMKUjIgPC0gZnVuY3Rpb24obW9kZWwpewogIHdhcm5pbmcoIkNvbmRpdGlvbmFsIFIyIGlzIG5vdCBtZWFuaW5nZnVsIGFuZCB0aGUgc2FtZSBhcyBtYXJnaW5hbCBSMlxuIikKICAKICAjIGZpeGVkIGVmZmVjdCB2YXJpYW5jZQogIGZpeCA8LSB2YXIoYXMubnVtZXJpYyhhcy52ZWN0b3IobW9kZWwkYikgJSolIHQoYXMubWF0cml4KG1vZGVsJFgpKSkpCiAgCiAgIyBtYXJnaW5hbAogIFIybSA8LSBmaXggLyAoZml4ICsgc3VtKG1vZGVsJHNpZ21hMikpCiAgUjIKICAjUm0gPC0gcm91bmQoMTAwKlIybSwgMykKICAKICAjIGNvbmRpdGlvbmFsCiAgUjJjIDwtIChmaXggKyBzdW0obW9kZWwkc2lnbWEyKSAtIG1vZGVsJHNpZ21hMltsZW5ndGgobW9kZWwkc2lnbWEyKV0pIC8gCiAgICAoZml4ICsgc3VtKG1vZGVsJHNpZ21hMikpCiAgCiAgUjJzIDwtIGMoUjJfbWFyZ2luYWwgPSBSMm0sIFIyX2NvZGl0aW9uYWwgPSBSMmMpCiAgcmV0dXJuKFIycykKfQoKCiMnIFRpdGxlOiB0aGUgZnVuY3Rpb24gdG8gZ2V0IGVzdGltYXRlcyBmcm9tIHJtYSBvYmplY3RzIChtZXRhZm9yKQojJwojJyBAcGFyYW0gbW9kZWw6IHJtYS5tdiBvYmplY3QgCiMnIEBwYXJhbSBtb2Q6IHRoZSBuYW1lIG9mIGEgbW9kZXJhdG9yIApnZXRfZXN0IDwtIGZ1bmN0aW9uIChtb2RlbCwgbW9kID0gIiAiKSB7CiAgCiAgbmFtZSA8LSBhcy5mYWN0b3Ioc3RyX3JlcGxhY2Uocm93Lm5hbWVzKG1vZGVsJGJldGEpLCBtb2QsICIiKSkKICBlc3RpbWF0ZSA8LSBhcy5udW1lcmljKG1vZGVsJGJldGEpCiAgbG93ZXJDTCA8LSBtb2RlbCRjaS5sYgogIHVwcGVyQ0wgPC0gbW9kZWwkY2kudWIgCiAgCiAgdGFibGUgPC0gdGliYmxlKG5hbWUgPSBuYW1lLCBlc3RpbWF0ZSA9IGVzdGltYXRlLCBsb3dlckNMID0gbG93ZXJDTCwgdXBwZXJDTCA9IHVwcGVyQ0wpCn0KCgojJyBUaXRsZTogdGhlIGZ1bmN0aW9uIHRvIGdldCBwcmVkaWN0aW9uIGludGVydmFscyAoY3JlZGlibGl0eSBpbnRlcnZhbHMpIGZyb20gcm1hIG9iamVjdHMgKG1ldGFmb3IpCiMnCiMnIEBwYXJhbSBtb2RlbDogcm1hLm12IG9iamVjdCAKIycgQHBhcmFtIG1vZDogdGhlIG5hbWUgb2YgYSBtb2RlcmF0b3IgCmdldF9wcmVkIDwtIGZ1bmN0aW9uIChtb2RlbCwgbW9kID0gIiAiKSB7CiAgbmFtZSA8LSBhcy5mYWN0b3Ioc3RyX3JlcGxhY2Uocm93Lm5hbWVzKG1vZGVsJGJldGEpLCBtb2QsICIiKSkKICBsZW4gPC0gbGVuZ3RoKG5hbWUpCiAgCiAgaWYobGVuICE9IDEpewogIG5ld2RhdGEgPC0gbWF0cml4KE5BLCBuY29sID0gbGVuLCBucm93ID0gbGVuKQogIGZvcihpIGluIDE6bGVuKSB7CiAgICAjIGdldHRpbmcgdGhlIHBvc2l0aW9uIG9mIHVuaXF1ZSBjYXNlIGZyb20gWCAoZGVzaWduIG1hdHJpeCkKICAgIHBvcyA8LSB3aGljaChtb2RlbCRYWyxpXSA9PSAxKVtbMV1dCiAgICBuZXdkYXRhWywgaV0gPC0gbW9kZWwkWFtwb3MsXQogICAgfQogIHByZWQgPC0gcHJlZGljdC5ybWEobW9kZWwsIG5ld21vZHMgPSBuZXdkYXRhKQogIH0KICBlbHNlIHsKICAgIHByZWQgPC0gcHJlZGljdC5ybWEobW9kZWwpCiAgICB9CiAgbG93ZXJQUiA8LSBwcmVkJGNyLmxiCiAgdXBwZXJQUiA8LSBwcmVkJGNyLnViIAogIAogIHRhYmxlIDwtIHRpYmJsZShuYW1lID0gbmFtZSwgbG93ZXJQUiA9IGxvd2VyUFIsIHVwcGVyUFIgPSB1cHBlclBSKQp9CgojSGVyZSBhcmUgbGlua3MgZm9yIGhvdyB0byBkbyBjb25maWRlbmNlIHJlZ2lvbnMgZm9yIHJtYS5tdiByZWdyZXNzaW9uIGxpbmVzCiNodHRwczovL3d3dy5yZG9jdW1lbnRhdGlvbi5vcmcvcGFja2FnZXMvbWV0YWZvci92ZXJzaW9ucy8xLjktOS90b3BpY3MvcHJlZGljdC5ybWEKI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzUwODA0NDY0L291dC1vZi1zYW1wbGUtcHJlZGljdGlvbi1mb3Itcm1hLW9iamVjdC1pbi1tZXRhZm9yCgoKIycgVGl0bGU6IENvbnRyYXN0IG5hbWUgZ2VuZWF0b3IKIycKIycgQHBhcmFtIG5hbWU6IGEgdmVjdG9yIG9mIGNoYXJhY3RlciBzdHJpbmdzCmNvbnRfZ2VuIDwtIGZ1bmN0aW9uIChuYW1lKSB7CiAgY29tYmluYXRpb24gPC0gY29tYm4obmFtZSwyKQogIG5hbWVfZGF0IDwtIHQoY29tYmluYXRpb24pCiAgbmFtZXMgPC0gcGFzdGUobmFtZV9kYXRbICwxXSwgbmFtZV9kYXRbLCAyXSwgc2VwID0gIi0iKQogIHJldHVybihuYW1lcykKfQpgYGAKCgojIyBBcHBlbmRpeCBTMTogU3VwcGxlbWVudGFyeSBNZXRob2RzCgojIyMgU3VwcGxlbWVudGFyeSBpbmZvcm1hdGlvbiBmb3IgdGhlIGxpdGVyYXR1cmUgc2VhcmNoCgojIyMjIFRhYmxlIFMxLjEKQ2l0YXRpb25zIGZvciBwYXBlcnMgZGVzY3JpYmluZyB0aGUgbWFpbiBtZXRob2RzIG9mIGNvcGh5bG9nZW55IGFuYWx5c2lzLCBiYXNlZCBvbiBhICpHb29nbGUgU2Nob2xhciogc2VhcmNoIGNvbmR1Y3RlZCBvbiA0dGggSnVseSAyMDE5LiBBbHRob3VnaCB0aGUgcGFwZXIgZGVzY3JpYmluZyBCcm9va3MgcGFyc2ltb255IGFuYWx5c2lzIGhhcyBtb3JlIGNpdGF0aW9ucyB0aGFuIHRoYXQgZGVzY3JpYmluZyB0aGUgUGFyYWZpdCBtZXRob2QsIHJlbGF0aXZlbHkgZmV3IGNpdGF0aW9ucyBjb3JyZXNwb25kIHRvIGFjdHVhbCBjb3BoeWxvZ2VuZXRpYyBhbmFseXNlcyBlbXBsb3lpbmcgdGhlIGFwcHJvYWNoLCAqdmVyc3VzKiBtZXRob2RvbG9naWNhbCBkaXNjdXNzaW9uLgoKYGBge3J9CiMgZ2V0dGluZyB0aGUgZGF0YSBhbmQgZm9ybWF0aW5nIHNvbWUgdmFyaWFibGVzICh0dXJuaW5nIGNocmFyYWN0ZXIgdmVjdG9ycyB0byBmYWN0b3JzKQpyZWFkX2NzdihoZXJlKCJkYXRhL2xpdF9zZWFyY2guY3N2IiksIG5hID0gIk5BIikgJT4lIAogICBtdXRhdGVfaWYoaXMuY2hhcmFjdGVyLCBhcy5mYWN0b3IpICU+JSAga2FibGUoImh0bWwiKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKIyMgVGhlIENvcGh5bG9nZW55IERhdGFzZXQKCiMjIyBUYWJsZSBvZiB0aGUgZGF0YXNldAoKQmVsb3cgaXMgdGhlIGRhdGFzZXQgdXNlZCBmb3Igb3VyIG1ldGEtYW5hbHlzaXMsIGZvbGxvd2VkIGJ5IGV4cGxhbmF0aW9ucyBvZiAyNCB2YXJpYWJsZXMgZXh0cmFjdGVkIGZyb20gdGhlIHBhcGVycyBpbmNsdWRlZCAobm90IGFsbCB2YXJpYWJsZXMgd2VyZSB1c2VkIGZvciBvdXIgYW5hbHlzZXM7IHZhcmlhYmxlcyB3aGljaCB3ZXJlIG5laXRoZXIgJ2RpcmVjdGx5JyBub3IgJ2luZGlyZWN0bHknIHVzZWQgaW4gb3VyIGFuYWx5c2VzIGFyZSBpbmRpY2F0ZWQgYnkgKikuCgojIyMjIFRhYmxlIFMxLjIKVGhlIG1ldGEtYW5hbHl0aWMgZGF0YXNldCBvZiB0aGlzIHN0dWR5LgoKYGBge3J9CiMgZ2V0dGluZyB0aGUgZGF0YSBhbmQgZm9ybWF0aW5nIHNvbWUgdmFyaWFibGVzICh0dXJuaW5nIGNocmFyYWN0ZXIgdmVjdG9ycyB0byBmYWN0b3JzKQpmdWxsX2RhdGEgPC0gcmVhZF9jc3YoaGVyZSgiZGF0YS8yMDIxLTA5LTAxLXNvdXJjZS1kYXRhLWRhdC5jc3YiKSwgbmEgPSAiTkEiKSAlPiUgCiAgIG11dGF0ZV9pZihpcy5jaGFyYWN0ZXIsIGFzLmZhY3RvcikKCiMgZGF0YXNldCB0byBjb21wYXJlIHRoZSBzYW1lIGNvcGh5bG9nZW5pZXMgYmV0d2VlbiB0aGUgdHdvIG1ldGhvZHMKCmZ1bGxfcGFpciA8LSByZWFkX2NzdihoZXJlKCJkYXRhLzIwMjAtMDgtMTItcGFyaWVkLmNzdiIpLCBuYSA9ICJOQSIpICU+JSAKICAgbXV0YXRlX2lmKGlzLmNoYXJhY3RlciwgYXMuZmFjdG9yKQoKIyBtYWtpbmcgYSBzY3JvbGxhYmxlIHRhYmxlCmthYmxlKGZ1bGxfZGF0YSwgImh0bWwiKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICI1MDBweCIpCmBgYAoKQS4gX19hdXRob3JzX186IFRoZSBhdXRob3JzIG9mIHRoZSBzdHVkeSBhbmQgdGhlIGRhdGUgKGNpdGF0aW9uIGZvcm0pLgoKQi4gX195ZWFyX186IFRoZSB5ZWFyIG9mIHB1YmxpY2F0aW9uIG9mIHRoZSBzdHVkeS4KCkMuIF9faG9zdF90YXhfYnJvYWRfXzoJU2VwYXJhdGlvbiBvZiB0aGUgaG9zdCBncm91cCBhY2NvcmRpbmcgdG8gYnJvYWRlciB0YXhvbm9taWMgdW5pdHMgKGUuZy4gdmVydGVicmF0ZSwgaW52ZXJ0ZWJyYXRlLCBtaWNyb2JlLCBwbGFudCkuCgpELiBfX3N5bWJpb250X3RheF9icm9hZF9fOglTZXBhcmF0aW9uIG9mIHRoZSBzeW1iaW9udCBncm91cCBhY2NvcmRpbmcgdG8gYnJvYWRlciB0YXhvbm9taWMgdW5pdHMgKGUuZy4gdmVydGVicmF0ZSwgaW52ZXJ0ZWJyYXRlLCBtaWNyb2JlLCBwbGFudCkuCgpFLiBfX3N5bWJpb250X2V1a19fKjoJV2hldGhlciB0aGUgc3ltYmlvbnQgaXMgZXVrYXJ5b3RpYyAoc3RhdGUgPSd5ZXMnKSwgb3IgcHJva2FyeW90aWMgKHN0YXRlPSdubycpLgoKRi4gX19zeW1iaW9zaXNfXzoJVGhlIHR5cGUgb2Ygc3ltYmlvbnQgKGUuZy4gcGFyYXNpdGUgb3IgbXV0dWFsaXN0KS4gRm9yIHRoaXMgd2UgZm9sbG93ZWQgdGhlIGRlZmluaXRpb24gdXNlZCBieSB0aGUgYXV0aG9ycyBvZiB0aGUgc3R1ZHkuCgpHLiBfX2VuZG9fb3JfZWN0b19fOglXaGV0aGVyIHRoZSBzeW1iaW9udCBsaXZlcyBvdXRzaWRlIHRoZSBob3N0IChpLmUuIGlzIGFuIGVjdG9zeW1iaW9udCksIG9yIGluc2lkZSB0aGUgaG9zdCAoaS5lLiBpcyBhbiBlbmRvc3ltYmlvbnQpLgoKSC4gX19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZF9fOglXaGV0aGVyIHRoZSBzeW1iaW9udCBpcyB0cmFuc21pdHRlZCB2ZXJ0aWNhbGx5LCBob3Jpem9udGFsbHksIG9yIGJvdGguIEZvciB0aGlzLCB3ZSBmb2xsb3dlZCB0aGUgcm91dGUgb2YgdHJhbnNtaXNzaW9uIHNwZWNpZmllZCBieSB0aGUgYXV0aG9ycyBvZiB0aGUgc3R1ZHkuCgpJLiBfX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2ZpbmVfXyo6CUEgZmluZXItc2NhbGUgZGVzY3JpcHRpb24gb2YgdGhlIG1vZGUgb2YgdHJhbnNtaXNzaW9uIG9mIHRoZSBzeW1iaW9udCAoZS5nLiBjb250YWN0LCB2ZWN0b3IsIGJvZGlseSBmbHVpZCwgdmVydGljYWwsIHRyb3BoaWMpLgoKSi4gX19WaXNpdGluZ19zeW1iaW9udD9fXyoJV2hldGhlciB0aGUgc3ltYmlvbnQgaXMgcmVzaWRlbnQgb24gdGhlIGhvc3QgKHJlc2lkZW50KSwgb3IgbWFrZXMgdmlzaXRzIHRvIHRoZSBob3N0IG9yIGhvc3RzICh2aXNpdG9yKS4KCksuIF9faG9zdF90aXBzX2xpbmtlZF9fOglUaGUgbnVtYmVyIG9mIGluZGl2aWR1YWwgaG9zdCB0YXhhIGluY2x1ZGVkIGluIHRoZSBjb3BoeWxvZ2VuZXRpYyBhbmFseXNpcy4KCkwuIF9faG9zdF90aXBzX2xpbmtlZF9jb3JyZWN0ZWRfXwlUaGUgc2FtZSBtZWFzdXJlIGFzIGZvciBjb2x1bW4gSywgJ2hvc3RfdGlwc19saW5rZWQnLCBidXQgcmVkdWNlZCB0byBvbmx5IGluY2x1ZGUgb25lIG1lbWJlciBvZiBlYWNoIGhvc3Qgc3BlY2llcy4gVGhpcyBpcyBpbmNsdWRlZCBiZWNhdXNlIHNvbWUgYXV0aG9ycyBpbmNsdWRlIG11bHRpcGxlIGluZGl2aWR1YWxzIG9mIHRoZSBzYW1lIGhvc3Qgc3BlY2llcy4gV2l0aG91dCBjb3JyZWN0aW9uLCB0aGlzIGFydGlmaWNpYWxseSBpbmNyZWFzZXMgdGhlIGFwcGFyZW50IG51bWJlciBvZiBob3N0IHNwZWNpZXMgaW5jbHVkZWQgaW4gdGhlIHN0dWR5LgoKTS4gX19ob3N0X2dlbmVyYV9fOglBIGNvdW50IG9mIHRoZSBudW1iZXIgb2YgaG9zdCBnZW5lcmEgaW5jbHVkZWQgaW4gdGhlIGNvcGh5bG9nZW5ldGljIGFuYWx5c2lzLgoKTi4gX190b3RhbF9ob3N0X3N5bWJpb250X2xpbmtzX18JVGhlIHRvdGFsIG51bWJlciBvZiBsaW5rcyBiZXR3ZWVuIGhvc3QgYW5kIHN5bWJpb250IHRheGEgcmVjb3JkZWQgaW4gYSBzdHVkeS4gSWYgYWxsIHN5bWJpb250cyB3ZXJlIHN0cmljdCBzcGVjaWFsaXN0cywgdGhpcyB3b3VsZCBlcXVhbCB0aGUgbnVtYmVyIG9mIHN5bWJpb250cyBpbmNsdWRlZCBpbiB0aGUgc3R1ZHkuIEhvd2V2ZXIsIGJlY2F1c2Ugc3ltYmlvbnRzIGFyZSBvZnRlbiBhc3NvY2lhdGVkIHdpdGggbW9yZSB0aGFuIG9uZSBob3N0LCB0aGlzIHZhbHVlIGlzIG9mdGVuIGhpZ2hlciB0aGFuIHRoZSB0b3RhbCBudW1iZXIgb2Ygc3ltYmlvbnRzIGluY2x1ZGVkIGluIHRoZSBzdHVkeS4KCk8uIF9faG9zdF9yYW5nZV9saW5rX3JhdGlvX186CUFuIGVzdGltYXRpb24gb2Ygc3ltYmlvbnQgaG9zdCBzcGVjaWZpY2l0eSwgY2FsY3VsYXRlZCBieSBkaXZpZGluZyB0aGUgdG90YWwgbnVtYmVyIG9mIGxpbmtzIGJldHdlZW4gaG9zdHMgYW5kIHN5bWJpb250cyAoaS5lLiAndG90YWxfaG9zdF9zeW1iaW9udF9saW5rcycsIGNvbHVtbiBOKSwgYnkgdGhlIHRvdGFsIG51bWJlciBvZiBzeW1iaW9udHMgaW5jbHVkZWQgaW4gdGhlIHN0dWR5IChpLmUuICdzeW1iaW9udF90aXBzX2xpbmtlZCcsIGNvbHVtbiBRKS4KClAuIF9faG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aF9fOglBbiBhbHRlcm5hdGl2ZSBlc3RpbWF0aW9uIG9mIHN5bWJpb250IGhvc3Qgc3BlY2lmaWNpdHksIGNhbGN1bGF0ZWQgYnkgZmlyc3Qgc3VtbWluZyB0aGUgbnVtYmVyIG9mIGhvc3QgdGF4b25vbWljIHJhbmtzIGxpbmtlZCB0byBlYWNoIHN5bWJpb250IChpLmUuIHNpbmdsZSBob3N0IHNwZWNpZXMgPSAxLCBtdWx0aXBsZSBob3N0IHNwZWNpZXMgaW4gdGhlIHNhbWUgZ2VudXMgPSAyLCBtdWx0aXBsZSBob3N0IGdlbmVyYSA9IDMsIG11bHRpcGxlIGhvc3QgZmFtaWxpZXMgPSA0LCBtdWx0aXBsZSBob3N0IG9yZGVycyA9IDUpLCBhbmQgZGl2aWRpbmcgYnkgdGhlIHRvdGFsIG51bWJlciBvZiBzeW1iaW9udHMgaW5jbHVkZWQgaW4gdGhlIHN0dWR5IChpLmUuICdzeW1iaW9udF90aXBzX2xpbmtlZCcsIGNvbHVtbiBRKS4KClEuIF9fc3ltYmlvbnRfdGlwc19saW5rZWRfXwlUaGUgbnVtYmVyIG9mIGluZGl2aWR1YWwgc3ltYmlvbnQgdGF4YSBpbmNsdWRlZCBpbiB0aGUgY29waHlsb2dlbmV0aWMgYW5hbHlzaXMuCgpSLiBfX3N5bWJpb250X2dlbmVyYV9fOglBIGNvdW50IG9mIHRoZSBudW1iZXIgb2Ygc3ltYmlvbnQgZ2VuZXJhIGluY2x1ZGVkIGluIHRoZSBjb3BoeWxvZ2VuZXRpYyBhbmFseXNpcy4KClMuIF9fbm9fcmFuZG9taXphdGlvbnNfXzoJVGhlIG51bWJlciBvZiBwaHlsb2dlbmV0aWMgcmFuZG9taXphdGlvbnMgcGVyZm9ybWVkIGR1cmluZyB0aGUgY29waHlsb2dlbmV0aWMgYW5hbHlzaXMuCgpULiBfX3BfdmFsdWVfXzoJVGhlIHAtdmFsdWUgcmVwb3J0ZWQgZm9yIHRoZSBjb3BoeWxvZ2VuZXRpYyBhbmFseXNpcywgcmVwcmVzZW50aW5nIHRoZSBsaWtlbGlob29kIHRoYXQgaG9zdCBhbmQgc3ltYmlvbnQgcGh5bG9nZW5pZXMgZGlzcGxheSBjb3NwZWNpYXRpb24uCgpVLiBfX21ldGhvZF9fOglXaGV0aGVyIFRyZWVNYXAgb3IgUGFyYUZpdCB3YXMgdXNlZCB0byBvYnRhaW4gdGhlIHJlcG9ydGVkIHAgdmFsdWUuCgojIyMgVGFibGUgb2Ygc2FtcGxlIHNpemVzCgpCZWxvdyB3ZSBwcmVzZW50IG91ciBzYW1wbGUgc2l6ZXMgZm9yIHRoZSB0d28gc2VwYXJhdGUgbWV0aG9kczogVHJlZU1hcCBbQHBhZ2UxOTk0cGFyYWxsZWxdIGFuZCBQYXJhRml0IFtAbGVnZW5kcmUyMDAyc3RhdGlzdGljYWxdIChhbmQgY29tYmluZWQpLCBpbiB0ZXJtcyBvZiBlZmZlY3Qgc2l6ZXMsIHBhcGVycywgYW5kIGRpZmZlcmVudCBsZXZlbHMgb2YgY2F0ZWdvcmljYWwgdmFyaWFibGVzIChmYWN0b3JzKS4gICAKCmBgYHtyfQojIHNlbGVjdGluZyBvdXQgdmFyaWFibGVzLCB3aGljaCB3ZSB1c2VkIGZvciBvdXIgYW5hbHlzaXMKZGF0IDwtIGZ1bGxfZGF0YSAlPiUgc2VsZWN0KC1zeW1iaW9udF9ldWssIC1tb2RlX29mX3RyYW5zbWlzc2lvbl9maW5lLCAtYFZpc2l0aW5nX3N5bWJpb250P2ApCnBhaXIgPC0gZnVsbF9wYWlyICU+JSBzZWxlY3QoLXN5bWJpb250X2V1aywgLW1vZGVfb2ZfdHJhbnNtaXNzaW9uX2ZpbmUsIC1gVmlzaXRpbmdfc3ltYmlvbnQ/YCkKCiMgbWFraW5nIGEgdGFibGUgb2Ygc2FtcGxlIHNpemVzIGZvciBkaWZmZXJlbnQgdmFyaWFibGVzCmRhdCAlPiUgZ3JvdXBfYnkobWV0aG9kKSAlPiUgCiAgc3VtbWFyaXNlKAogICAgYEVmZmVjdCBzaXplcyAoYW5hbHlzZXMpYCA9IG4oKSwKICAgIFN0dWRpZXMgPSBuKCksIAogICAgUGFwZXJzID0gbl9kaXN0aW5jdChhdXRob3JzKSwKICAgIGBWZXJ0ZWJyYXRlIGhvc3RzYCA9IHN1bShob3N0X3RheF9icm9hZCA9PSAiVmVydCIsIG5hLnJtID0gVCksICMgbmEucm0gaXMgaW1wb3J0YW50IHdoZW4gTkEgZXhpc3RzCiAgICBgSW52ZXJ0ZWJyYXRlIGhvc3RzYCA9IHN1bShob3N0X3RheF9icm9hZCA9PSAiSW52ZXJ0IiwgbmEucm0gPSBUKSwKICAgIGBQbGFudCBob3N0c2AgID0gc3VtKGhvc3RfdGF4X2Jyb2FkID09ICJQbGFudCIsIG5hLnJtID0gVCksCiAgICBgTWljcm9iZSBob3N0c2AgPSBzdW0oaG9zdF90YXhfYnJvYWQgPT0gIk1pY3JvYmUiLCBuYS5ybSA9IFQpLAogICAgYFZlcnRlYnJhdGUgc3ltYmlvbnRzYCA9IHN1bShzeW1iaW9udF90YXhfYnJvYWQgID09ICJWZXJ0IiwgbmEucm0gPSBUKSwKICAgIGBJbnZlcnRlYnJhdGUgc3ltYmlvbnRzYCA9IHN1bShzeW1iaW9udF90YXhfYnJvYWQgID09ICJJbnZlcnQiLCBuYS5ybSA9IFQpLAogICAgYFBsYW50IHN5bWJpb250c2AgID0gc3VtKHN5bWJpb250X3RheF9icm9hZCAgPT0gIlBsYW50IiwgbmEucm0gPSBUKSwKICAgIGBNaWNyb2JlIHN5bWJpb250c2AgPSBzdW0oc3ltYmlvbnRfdGF4X2Jyb2FkICA9PSAiTWljcm9iZSIsIG5hLnJtID0gVCksCiAgICBgUGFyYXN0aWMgcmVsYXRpb25zaGlwc2AgPSBzdW0oc3ltYmlvc2lzID09ICJQYXJhc2l0ZSIsIG5hLnJtID0gVCksCiAgICBgTXV0dWFsaXN0aWMgcmVsYXRpb3NoaXBzYCA9IHN1bShzeW1iaW9zaXMgPT0gIk11dHVhbGlzdCIsIG5hLnJtID0gVCksCiAgICBgRWN0by1zeW1iaW9udHNgID0gc3VtKGVuZG9fb3JfZWN0byAgPT0gIkVjdG8iLCBuYS5ybSA9IFQpLAogICAgYEVuZG8tc3ltYmlvbnRzYCA9IHN1bShlbmRvX29yX2VjdG8gPT0gIkVuZG8iLCBuYS5ybSA9IFQpLAogICAgYEVjdG8vZW5kby1zeW1iaW9udHNgID0gc3VtKGVuZG9fb3JfZWN0byA9PSAiRW5kby9FY3RvIiwgbmEucm0gPSBUKSwKICAgIGBIb3Jpem9udGFsIHRyYW5zbWlzc2lvbmAgPSBzdW0obW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgID09ICJob3Jpem9udGFsIiwgbmEucm0gPSBUKSwKICAgIGBWZXJ0aWNhbCB0cmFuc21pc3Npb25gID0gc3VtKG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkID09ICJ2ZXJ0aWNhbCIsIG5hLnJtID0gVCksCiAgICBgSG9yaXpvbnRhbC92ZXJ0aWNhbC10cmFuc21pc3Npb25gID0gc3VtKG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkID09ICJib3RoIiwgbmEucm0gPSBUKQogICkgLT4gbl90YWJsZTEKCiMgdHJhbnNwb3NpbmcgdGhlIHRhYmxlIGFuZCBjcmVhdGluZyB0aGF0IHRhYmxlIGFuZCBhZGRpbmcgYSBjb3JyZWN0IG51bWJlciBvZiB0aGUgcGFwZXJzIGZvciBgQ29tYmluZWRgCm5fYXV0aG9ycyA8LSBuX2Rpc3RpbmN0KGRhdCRhdXRob3JzKSAjIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFwZXJzCmRhdCRzdHVkaWVzIDwtIHBhc3RlMChkYXQkYXV0aG9ycywgZGF0JGhvc3RfdGF4X2ZpbmUsIGRhdCRzeW1iaW9udF90YXhfZmluZSwgZGF0JHRvdGFsX2hvc3Rfc3ltYmlvaW50X2xpbmtzKSAjIHRoZSBudW1iZXIgb2YgYW5hbHlzZXMgKHN0dWRpZXMpCm5fc3R1ZGllcyA8LSBuX2Rpc3RpbmN0KGRhdCRzdHVkaWVzKQpuX3RhYmxlMiA8LXQobl90YWJsZTFbLC0xXSkKY29sbmFtZXMobl90YWJsZTIpIDwtIG5fdGFibGUxJG1ldGhvZApuX3RhYmxlMiAlPiUgYXNfdGliYmxlKHJvd25hbWVzID0gIk51bWJlciIpICU+JSAKICBtdXRhdGUoQ29tYmluZWQgPSBQYXJhZml0ICsgVHJlZU1hcCwgQ29tYmluZWQgPSByZXBsYWNlKENvbWJpbmVkLCBjKDIsMyksIGMobl9zdHVkaWVzLCBuX2F1dGhvcnMpKSkgJT4lICAKICByZW5hbWUoIk51bWJlciBvZiIgPSAiTnVtYmVyIiwgIlBhcmFGaXQgKG4pIiA9ICJQYXJhZml0IiwgIlRyZWVNYXAgKG4pIiA9ICJUcmVlTWFwIiwgICJDb21iaW5lZCAobikiID0gIkNvbWJpbmVkIikgJT4lIAogIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjI1MHB4IikKICAjcGFuZGVyKHNwbGl0LmNlbGwgPSA0MCwgc3BsaXQudGFibGUgPSBJbmYpICMgbm90IGFzIG5pY2UgYXMga2FibGUKYGBgCk5vdGUgdGhhdCB0aGUgbnVtYmVycyBvZiBzdHVkaWVzIGFuZCBwYXBlcnMgZG9lcyBub3QgYWRkIHVwIChUcmVlTWFwICsgUGFyYUZpdCAkXG5lcSQgQ29tYmluZWQpLCBiZWNhdXNlIGByIHN1bShuX3RhYmxlMlsyLF0pIC0gbGVuZ3RoKHVuaXF1ZShkYXQkc3R1ZGllcykpYCBhbmFseXNlcyBhbmQgYHIgc3VtKG5fdGFibGUyWzMsXSkgLSBsZW5ndGgodW5pcXVlKGRhdCRhdXRob3JzKSlgICBwYXBlcnMgdXNlZCBib3RoIHRoZSBUcmVlTWFwIGFuZCBQYXJhRml0IG1ldGhvZHMgKHRoZSB0ZXJtICJwYXBlcnMiIGhlcmUgaXMgb3VyIHZhcmlhYmxlIGBhdXRob3JzYCkKCiMjIyBNaXNzaW5nIGRhdGEgcGF0dGVybnMKCkJlbG93LCB3ZSBwcmVzZW50IHRoZSBudW1iZXIgb2YgaW5zdGFuY2VzIG9mIG1pc3NpbmcgZGF0YSAoY2VsbHMpIGZvciBhbGwgdmFyaWFibGVzIHVzZWQgaW4gb3VyIG1ldGEtYW5hbHlzaXMuCgpgYGB7cn0KIyBzdW1tYXJpbmcgbWlzc2luZ25lc3MgaW4gb3VyIGRhdGFzZXQKIyBmdW5zKHN1bShpcy5uYSguKSkpIG5lZWRzIHRvIGJlIGluIGZ1bnMgYXMgaXMubmEgaGFzICIuIiA9IGVhY2ggY29sdW1uCmRhdCAlPiUgc3VtbWFyaXNlX2FsbCh+c3VtKGlzLm5hKC4pKSkgJT4lICMgbWFwKH5zdW0oaXMubmEoLikpICMgdGhpcyBpcyBhbiBhbHRlcmFudGl2ZSB3YXkgCiAgdCgpICU+JSBhc190aWJibGUocm93bmFtZXMgPSAiVmFyaWFibGUiKSAlPiUgCiAgcmVuYW1lKCJOdW1iZXIgb2YgbWlzc2luZyBkYXRhIChuKSIgPSAiVjEiKSAlPiUgCiAgI3BhbmRlcihzcGxpdC5jZWxsID0gNDAsIHNwbGl0LnRhYmxlID0gSW5mKQogIGthYmxlKCkgJT4lIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICI2MCUiLCBoZWlnaHQgPSAiMjUwcHgiKQoKIyBhbiBhbHRlcm5hdGl2ZSBtZXRob2QgdXNpbmcgdGhlIG1pIHBhY2thZ2UKI21pc3NpbmdfZGF0YV90YmwgPC0gbWlzc2luZ19kYXRhLmZyYW1lKGFzLmRhdGEuZnJhbWUoZGF0YSkpCiNzaG93KG1pc3NpbmdfZGF0YV90YmwpIApgYGAKCiMjIEFwcGVuZGl4IFMyOiBNZXRhLWFuYWx5c2lzCgojIyMgQ2FsY3VsYXRpbmcgZWZmZWN0IHNpemVzCgpXZSBjcmVhdGVkIG91ciBlZmZlY3Qgc2l6ZSAoY29ycmVsYXRpb24gY29lZmZpY2llbnQgKnIqIGFuZCBpdHMgRmlzaGVyJ3MgeiB0cmFuc2Zvcm1hdGlvbiAqWnIqKSBmcm9tIHAgdmFsdWVzIGFuZCBhc3NvY2lhdGVkIHNhbXBsZSBzaXplcyBbQHJvc2VudGhhbDIwMDNyZXF1aXZhbGVudF0uIFdlIHVzZWQgaGFsZiBvZiB0aGUiZWZmZWN0aXZlIHNhbXBsZSBzaXplIiBmb3IgZWFjaCBlZmZlY3Qgc2l6ZSAoYW4gaW5kaWNhdG9yIG9mIGNvbmdydWVuY2UpOiAKCiQkCk5fe2VmZmVjdGl2ZX0gPSBcZnJhY3s0bl97aH1uX3tzfX0ge25fe2h9ICsgbl97c319LAokJAp3aGVyZSAkbl9oJCBhbmQgJG5fcyQgYXJlIHNhbXBsZSBzaXplIGZvciBob3N0cyBhbmQgc3ltYmlvbnRzIChpbiBvdXIgY2FzZTogYGhvc3RfdGlwc19saW5rZWRfY29ycmVjdGVkYCBhbmQgYHN5bWJpb250X3RpcHNfbGlua2VkYCkuIFdoZW4gJG4gPSBuX2ggPSBuX3MkLCAkTl97ZWZmZWN0aXZlfSQgc2ltcGxpZmllcyB0byAkMm4kLiBXZSB1c2VkICROX3tlZmZlY3RpdmV9LzIkLCB3aGljaCB3ZSBjYWxsZWQgdGhlIG51bWJlciBvZiAiZWZmZWN0aXZlIHBhaXJzIiAoJE5fe2VwfSQpIGFzIG91ciBzYW1wbGUgc2l6ZS4gCgpBbHNvLCB3ZSBjcmVhdGVkIGEgY29sdW1uIHdpdGggYSB1bmlxdWUgSUQgZm9yIGVhY2ggb2JzZXJ2YXRpb24gKGkuZS4gYW4gb2JzZXJ2YXRpb24gbGV2ZWwgcmFuZG9tIGVmZmVjdCksIHRlcm1lZCBgb2JzZXJ2YXRpb25gLCB3aGljaCBpcyByZXF1aXJlZCBmb3IgdGhlIGBybWEubXZgIGZ1bmN0aW9uIGluIGBtZXRhZm9yYCBbQHZpZWNodGJhdWVyMjAxMGNvbmR1Y3RpbmddLgoKYGBge3J9CmRhdCAlPD4lIAogICMgZ2V0dGluZyBzYW1wbGUgc2l6ZSAmIG9ic2VydmF0aW9uIGxldmVsIHJhbmRvbSBlZmZlY3QKICBtdXRhdGUoLiwgc2FtcGxlX3NpemUgPSAyKihob3N0X3RpcHNfbGlua2VkX2NvcnJlY3RlZCpzeW1iaW9udF90aXBzX2xpbmtlZCkvKGhvc3RfdGlwc19saW5rZWRfY29ycmVjdGVkICsgc3ltYmlvbnRfdGlwc19saW5rZWQpLAogICAgICAgICBvYnNlcnZhdGlvbiA9IGZhY3RvcigxOm5yb3coLikpKSAjLCBzaWduZmljYW5jZSA9IGlmX2Vsc2UocF92YWx1ZSA8PSAwLjA1LCAieSIsICJuIikgKSAKCiMgbWFraW5nIHAgPSAxIHRvIHAgPSAobm9fcmFuZG9taXphdGlvbiAtIDEpL25vX3JhbmRvbWl6YXRpb24gYXMgcCA9IDEgcHJvZHVjZXMgdCB2YWx1ZSA9IEluZgpkYXQkcF92YWx1ZSA8LSBpZmVsc2UoZGF0JHBfdmFsdWUgIT0gMSwgZGF0JHBfdmFsdWUsIChkYXQkbm9fcmFuZG9taXphdGlvbnMgLSAxKS9kYXQkbm9fcmFuZG9taXphdGlvbnMpIAoKIyBjYWxjdWxhdGluZyBlZmZlY3Qgc2l6ZSAKZGF0ICU8PiUgcF90b19acihwX3ZhbHVlLCBzYW1wbGVfc2l6ZSkgCgojIGdldHRpbmcgc2FtcGxlIHNpemUgZm9yIHNwcAojIHN1bShkYXQkc2FtcGxlX3NpemVbbWF0Y2godW5pcXVlKGRhdCRzdHVkaWVzKSwgZGF0JHN0dWRpZXMpXSkKCiMgZ2V0dGluZyBlZmZlY3Qgc2l6ZXMgZm9yIHBhaXIgZGF0YQpwYWlyICU8PiUgCiAgIyBnZXR0aW5nIHNhbXBsZSBzaXplICYgb2JzZXJ2YXRpb24gbGV2ZWwgcmFuZG9tIGVmZmVjdAogIG11dGF0ZSguLCBzYW1wbGVfc2l6ZSA9IDIqKGhvc3RfdGlwc19saW5rZWRfY29ycmVjdGVkKnN5bWJpb250X3RpcHNfbGlua2VkKS8oaG9zdF90aXBzX2xpbmtlZF9jb3JyZWN0ZWQgKyBzeW1iaW9udF90aXBzX2xpbmtlZCksCiAgICAgICAgIG9ic2VydmF0aW9uID0gZmFjdG9yKDE6bnJvdyguKSkpICAKIAojIG1ha2luZyBwID0gMSB0byBwID0gKG5vX3JhbmRvbWl6YXRpb24gLSAxKS9ub19yYW5kb21pemF0aW9uIGFzIHAgPSAxIHByb2R1Y2VzIHQgdmFsdWUgPSBJbmYKcGFpciRwX3ZhbHVlX3RyZWUgPC0gaWZlbHNlKHBhaXIkcF92YWx1ZV90cmVlID09IDEsIDAuOTk5LCBwYWlyJHBfdmFsdWVfdHJlZSkgIAojIGNhbGN1bGF0aW5nIGVmZmVjdCBzaXplICAgCnBhaXIgJTw+JSBwX3RvX1pyKHBfdmFsdWVfcGFyYSwgc2FtcGxlX3NpemUpICU+JSAKICByZW5hbWUocnZhbF9wYXJhID0gcnZhbCwgWnJfcGFyYSA9IFpyLCBWWnJfcGFyYSA9IFZacikgJT4lIAogIHBfdG9fWnIocF92YWx1ZV90cmVlLCBzYW1wbGVfc2l6ZSkgJT4lIAogIHJlbmFtZShydmFsX3RyZWUgPSBydmFsLCBacl90cmVlID0gWnIsIFZacl90cmVlID0gVlpyKSAKCmBgYAoKIyMjIENvcnJlbGF0aW5nIHR3byBtZXRob2RzIG9uIHRoZSBzYW1lIGNvcGh5bG9nZW5ldGljIGRhdGEKCkluIDE2IHN0dWRpZXMsIGF1dGhvcnMgdXNlZCBib3RoIGBQYXJhRml0YCBhbmQgYFRyZWVNYXBgIG9uIHRoZSBzYW1lIGNvcGh5bG9nZW55IGRhdGFzZXQsIGJ1dCBpbiBzb21lIG9mIHRoZXNlIHN0dWRpZXMsIHRoZXkgdXNlZCBkaWZmZXJlbnQgbnVtYmVycyBvZiByYW5kb21pemF0aW9uIGJldHdlZW4gdGhlIHR3byBtZXRob2RzLiBBbW9uZyB0aGVzZSAxNiwgMTEgc3R1ZGllcyB1c2VkIGBQYXJhRml0YCBhbmQgYFRyZWVNYXBgIHdpdGggdGhlIHNhbWUgb3Igc2ltaWxhciBudW1iZXIgb2YgcmFuZG9taXphdGlvbiAoZS5nLiwgOTk5IGFuZCAxLDAwMCkuIFdlIGhlcmUgY29ycmVsYXRlZCBlZmZlY3Qgc2l6ZXMgKFpyKSBiZXR3ZWVuIHRoZXNlIHR3byBtZXRob2RzLiBJbiB0aGUgZm9sbG93aW5nIGFuYWx5c2VzLCB3ZSBhc3N1bWUgdGhlIHAtdmFsdWUgYmFzZWQgZWZmZWN0IHNpemUsIFpyfmVxdWl2YWxlbnQgKG9yIGp1c3QgWnIpIGlzIGVxdWl2YWxlbnQgZm9yIGJvdGggbWV0aG9kcy4gSW4gc3VjaCBhIGNhc2UsIHdlIHdvdWxkIHJlcXVpcmUgYSB0aWdodCBjb3JyZWxhdGlvbiBiZXR3ZWVuIHRoZSBtZXRob2QuCgpgYGB7cn0KCiMgcGxvdHRpbmcgIGNvcnJlbGF0aW9ucyBidXQgbm90IGRpc3BsYXllZAojIEEpCmNvcl8xIDwtIHJvdW5kKHdpdGgocGFpciwgY29yKFpyX3BhcmEsIFpyX3RyZWUpKSwgMykKY29yX3QxIDwtIHdpdGgocGFpciwgY29yLnRlc3QoWnJfcGFyYSwgWnJfdHJlZSkpCiAgICAgICAgICAgICAgIAphbGxfcGxvdCA8LSBnZ3Bsb3QocGFpciwgYWVzKFpyX3BhcmEsIFpyX3RyZWUpKSArIAogIGdlb21fcG9pbnQoKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpICsgCiAgICBsYWJzKHggPSAiWnIgKFBhcmFGaXQpIiwgeSA9ICJaciAoVHJlZU1hcCkiKSArIAogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMSwgeSA9IC0xLCBsYWJlbCA9IHBhc3RlKCJyID0gIiwgY29yXzEpKQoKIyBCKQpjb3JfMiA8LSByb3VuZCh3aXRoKHBhaXJbcGFpciRtYXRjaCA9PSAieSIsIF0sIGNvcihacl9wYXJhLCBacl90cmVlKSksIDMpCmNvcl90MiA8LSB3aXRoKHBhaXJbcGFpciRtYXRjaCA9PSAieSIsIF0sIGNvci50ZXN0KFpyX3BhcmEsIFpyX3RyZWUpKQoKcGFydF9wbG90IDwtIGdncGxvdChwYWlyW3BhaXIkbWF0Y2ggPT0gInkiLCBdLCBhZXMoWnJfcGFyYSwgWnJfdHJlZSkpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKwogICBsYWJzKHggPSAiWnIgKFBhcmFGaXQpIiwgeSA9ICJaciAoVHJlZU1hcCkiKSArIAogICAgYW5ub3RhdGUoInRleHQiLCB4ID0gMSwgeSA9IC0xLCBsYWJlbCA9IHBhc3RlKCJyID0gIiwgY29yXzIpKQoKY29tYl9wbG90IDwtIGFsbF9wbG90ICsgcGFydF9wbG90ICsgcGxvdF9hbm5vdGF0aW9uKHRhZ19sZXZlbHMgPSAiQSIsIHRhZ19zdWZmaXggPSAiKSIpCiNjb21iX3Bsb3QKYGBgCgpUaGVyZSBhcmUgc3Ryb25nIGFuZCBzaWduaWZpY2FudCBjb3JyZWxhdGlvbnMgaW4gZWZmZWN0IHNpemVzIChacikgYmV0d2VlbiBgUGFyYUZpdGAgYW5kIGBUcmVlTWFwYCAoZm9yIGFsbCB0aGUgMTYgc3R1ZGllcywgciA9IGByIGNvcl8xYCwgdCA9IGByIHJvdW5kKGNvcl90MSRzdGF0aXN0aWMgLCAzKWAsIGRmID0gYHIgYXMubnVtZXJpYyhjb3JfdDEkcGFyYW1ldGVyKWAsIHAgPSBgciByb3VuZChjb3JfdDEkcC52YWx1ZSw0KWAsIGFuZCBmb3IgdGhlIDExIHBlcmZlY3RseSBtYXRjaGluZyBzdHVkaWVzLCByID0gYHIgY29yXzJgLCB0ID0gYHIgcm91bmQoY29yX3QyJHN0YXRpc3RpYyAsIDMpYCwgZGYgPSBgciBhcy5udW1lcmljKGNvcl90MiRwYXJhbWV0ZXIpYCwgcCA9IGByIHJvdW5kKGNvcl90MiRwLnZhbHVlLDQpYCkuIFRoZXJlZm9yZSwgd2UgaGF2ZSBtYWRlIGFuIGFzc3VtcHRpb24gdGhhdCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gcCB2YWx1ZXMgZnJvbSB0aGVzZSB0d28gbWV0aG9kcyBjYW4gYmUgZXF1YXRlZCBpbiBvdXIgYW5hbHlzZXMgYmVsb3cuIAoKIyMjIE1ldGEtYW5hbHl0aWMgbW9kZWw6IHRlc3RpbmcgRmFocmVuaG9seidzIHJ1bGUKCkZpcnN0LCB3ZSBjaGVja2VkIHdoYXQgcmFuZG9tIGVmZmVjdHMgc2hvdWxkIGJlIHB1dCBpbnRvIHRoZSBtYWluIG1vZGVsLiBUbyBkbyB0aGlzIHdlIGZpdHRlZCB0d28gcmFuZG9tIGVmZmVjdHMsIGBhdXRob3JzYCAoaS5lLiBzdHVkeSBJRHMpIGFuZCBgb2JzZXJ2YXRpb25gOyB0aGUgZm9ybWVyIHRlcm0gd2FzIGFkZGVkIHRvIGFjY291bnQgZm9yIG5vbi1pbmRlcGVuZGVuY2Ugb2YgZWZmZWN0IHNpemVzIG9yaWdpbmF0aW5nIGZyb20gdGhlIHNhbWUgcGFwZXJzIChpLmUuLCBgYXV0aG9yc2ApLiAKCmBgYHtyLCBjYWNoZT1UUlVFfQojIDIgcmFuZG9tIGVmZmVjdHMgJiBtb2RlbCBBSUMgCiMgbm90ZSB0aGF0IHByb2JhYmx5IG9ubHkgYmFzZSBzdHVmZiB3b3JrcyBvdXRzaWRlIG9mIG1haW4gY2h1bmNrIHNvIG5lZWQgdG8gY3JlYXRlIEFJQyBoZXJlCm1hX3Rlc3QxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgcmFuZG9tID0gbGlzdCh+IDEgfCBhdXRob3JzLCB+MXxvYnNlcnZhdGlvbiksIAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKYWljMSA8LSBBSUMobWFfdGVzdDEpCgojIDEgcmFuZG9tIGVmZmVjdCAmIG1vZGVsIEFJQyAKbWFfdGVzdDIgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmFpYzIgPC0gQUlDKG1hX3Rlc3QyKQpgYGAKClRoZSBtb2RlbCAoYG1hX3Rlc3QxYCksIHdoaWNoIGluY2x1ZGVkIGJvdGggcmFuZG9tIGZhY3RvcnMsIGhhZCBhIGxhcmdlciBBSUMgdmFsdWUgKGByIHJvdW5kKGFpYzEsMilgKSB0aGFuIHRoZSBtb2RlbCB3aXRoIG9ubHkgb25lIHJhbmRvbSBlZmZlY3QgKGByIHJvdW5kKGFpYzIsIDIpYCkgLiBUaGlzIGlzIGJlY2F1c2UgYG9ic2VydmF0aW9uYCBoYXJkbHkgYWNjb3VudGVkIGZvciBhbnkgdmFyaWFuY2UgKDwgMC4wMDAxKSBjb21wYXJlZCB0byBgYXV0aG9yc2AgKGByIHJvdW5kKG1hX3Rlc3QxJHNpZ21hMlsxXSwgNClgKS4gVGhlcmVmb3JlLCB3ZSBvbmx5IGluY2x1ZGVkIGBhdXRob3JzYCBhcyBvdXIgcmFuZG9tIGZhY3RvciBpbiBzdWJzZXF1ZW50IGFuYWx5c2VzLgoKV2UgcmFuIGludGVyY2VwdCBtb2RlbHMgKG1ldGEtYW5hbHlzZXMpIHdpdGggMyBkaWZmZXJlbnQgZGF0YXNldHMgKGBQYXJhRml0YCwgYFRyZWVNYXBgIGFuZCBib3RoIGNvbWJpbmVkOyBzZWUgdGhlIGV4cGxhbmF0aW9uIG9mIGBtZXRob2RgIGFib3ZlKS4gQWxzbywgd2Ugbm90ZSB0aGF0IHdlIHVzZWQgYWRqdXN0bWVudHMgZm9yIHRlc3Qgc3RhdGlzdGljcyBhbmQgY29uZmlkZW5jZSBpbnRlcnZhbHMgKGB0ZXN0ID0gInQiYCksIHdoaWNoIGlzIHNpbWlsYXIgdG8gKGJ1dCBub3QgdGhlIHNhbWUgYXMpIHRob3NlIHByb3Bvc2VkIGJ5IEtuYXBwIGFuZCBIYXJ0dW5nIFtAa25hcHAyMDAzaW1wcm92ZWRdOyBwcm9iYWJseSB0aGlzIGFwcHJvYWNoIGlzIG1vcmUgY29uc2VydmF0aXZlLgoKIyMjIyBSdW5uaW5nIE11bHRpbGV2ZWwgTWV0YS1hbmFseXRpYyBtb2RlbHMgd2l0aCAzIGRhdGFzZXRzCmBgYHtyLCBjYWNoZT1UUlVFfQojIHRoaW5rIGFib3V0IG1ha2luZyB0aGlzIGludG8gYSB0aWJibGUKIyBtZXRhLWFuYWx5c2lzIHdpdGggUGFyYWZpdAptYV9wYXJhZml0IDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgIHN1YnNldCA9IHdoaWNoKG1ldGhvZCA9PSAiVHJlZU1hcCIpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtYW5hbHlzaXMgd2l0aCBUcmVlTWFwCm1hX3RyZWVtYXAgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgc3Vic2V0ID0gd2hpY2gobWV0aG9kID09ICJQYXJhZml0IiksCiAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgbWV0YS1hbmFseXNpcyB3aXRoIGFsbCB0aGUgZGF0YSBjb21iaW5lZAptYV9hbGwgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKYGBgCgojIyMjIFRhYmxlIFMyLjEKT3ZlcmFsbCBlZmZlY3RzIChtZXRhLWFuYWx5dGljIG1lYW5zKSBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpIGJvdGggaW4gWnIgYW5kIHIsICBhbmQgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIGhldGVyb2dlbmVpdHksICpJKl4yXiAoSTIpIFtAaGlnZ2luczIwMDNtZWFzdXJpbmddIGZyb20gdGhlIGBtZXRhZm9yYCBtb2RlbCB1c2luZyB0aGUgMyBkYXRhc2V0cyAoYFBhcmFGaXRgLCBgVHJlZU1hcGAgYW5kIGJvdGggY29tYmluZWQsIG9yIGBBbGxgKS4gTm90ZSB0aGF0IGluIHRoZXNlIG1vZGVscywgKkkqXjJeflt0b3RhbF1+ID0gKkkqXjJeflthdXRob3JzXX4gKHNlZSBbQG5ha2FnYXdhMjAxMm1ldGhvZG9sb2dpY2FsO0BzZW5pb3IyMDE2aGV0ZXJvZ2VuZWl0eV0pLCBhcyB3ZSBvbmx5IGhhdmUgb25lIHJhbmRvbSBmYWN0b3IuIApgYGB7cn0KIyBnZXR0aW5nIEkyIGZvciB0aGUgbW9kZWxzCiMgY291bGQgdXNlIG1hcCgpCmkyX3RyZWVtYXAgPC0gSTIobWFfdHJlZW1hcCkKaTJfcGFyYWZpdCA8LSBJMihtYV9wYXJhZml0KQppMl9hbGwgPC0gSTIobWFfYWxsKQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIERhdGFzZXQgPSBjKCJQYXJhZml0IChacikiLCAiVHJlZU1hcCAoWnIpIiwgIkFsbCAoWnIpIiwgIlBhcmFmaXQgKHIpIiwgIlRyZWVNYXAgKHIpIiwgIkFsbCAocikiKSwKICBgT3ZlcmFsbCBtZWFuYCA9IGMobWFfcGFyYWZpdCRiLCBtYV90cmVlbWFwJGIsIG1hX2FsbCRiLCB0YW5oKG1hX3BhcmFmaXQkYiksIHRhbmgobWFfdHJlZW1hcCRiKSwgdGFuaChtYV9hbGwkYikpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMobWFfcGFyYWZpdCRjaS5sYiwgbWFfdHJlZW1hcCRjaS5sYiwgbWFfYWxsJGNpLmxiLCB0YW5oKG1hX3BhcmFmaXQkY2kubGIpLCB0YW5oKG1hX3RyZWVtYXAkY2kubGIpLCB0YW5oKG1hX2FsbCRjaS5sYikpLAogIGBVcHBlciBDICBbMC45NzVdYCA9IGMobWFfcGFyYWZpdCRjaS51YiwgbWFfdHJlZW1hcCRjaS51YiwgbWFfYWxsJGNpLnViLCAgdGFuaChtYV9wYXJhZml0JGNpLnViKSwgdGFuaChtYV90cmVlbWFwJGNpLnViKSwgdGFuaChtYV9hbGwkY2kudWIpKSwKICBgVlthdXRob3JzXWAgPSBjKG1hX3BhcmFmaXQkc2lnbWEyLCBtYV90cmVlbWFwJHNpZ21hMiwgbWFfYWxsJHNpZ21hMiwgcmVwKE5BLCAzKSksCiAgYEkyW3RvdGFsXWAgPSBjKGkyX3BhcmFmaXRbMV0sIGkyX3RyZWVtYXBbMV0sIGkyX2FsbFsxXSwgcmVwKE5BLCAzKSkpICU+JSAKICBrYWJsZSgiaHRtbCIsICBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKVGhlc2UgbW9kZWxzIGFsbCBnYXZlIGNvbnNpc3RlbnQgcmVzdWx0cyBpbmNsdWRpbmcgaGV0ZXJvZ2VuZWl0eS4gR2l2ZW4gdGhlc2UgcmVzdWx0cywgd2UgcHJvY2VlZGVkIHdpdGggb25seSBhbmFseXppbmcgdGhlIHdob2xlIGRhdGFzZXQgKGBBbGxgKSBmcm9tIGhlcmUgb24uICAgIAoKIyMjIyBGaWd1cmUgM2EKCmBgYHtyLCAgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9Mn0KIyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80MTkxOTAyMy9nZ3Bsb3QtYWRkaW5nLWltYWdlLW9uLXRvcC1yaWdodC1pbi10d28tcGxvdHMtd2l0aC1kaWZmZXJlbnQtc2NhbGVzCiMgaG93IHRvIGFkZCBwbmcgZmlsZXMgdG8gdGhlIGZpZ3VyZSAoYWJvdmUpCiMgcmVhZGluZyBpbWFnZQppbWFnZV9tdXR1YWxpc20gPC0gcmVhZFBORyhoZXJlKCJpbWFnZXMvbXV0dWFsaXNtX3RyYW5zcGFyZW50YmcucG5nIikpCmltYWdlX3BhcmFzaXRpc20gPC0gcmVhZFBORyhoZXJlKCJpbWFnZXMvcGFyYXNpdGlzbV90cmFuc3BhcmVudGJnLnBuZyIpKQoKIyBjcmVhdGluZyBhIHRhYmxlIG9mIHJlc3VsdHMKcHJlZF9tYSA8LSBnZXRfcHJlZChtYV9hbGwpIAplZmZlY3RfbWEgPC0gZ2V0X2VzdChtYV9hbGwpICU+JSBsZWZ0X2pvaW4ocHJlZF9tYSkgCgojIGNyZWF0aW5nIEFuIG9yY2hhcmQgcGxvdApmaWdfbWEgPC0gZ2dwbG90KGRhdGEgPSBlZmZlY3RfbWEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSAiT3ZlcmFsbCBtZWFuIikpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQsIGFlcyh4PSB0YW5oKFpyKSwgeSA9ICJPdmVyYWxsIG1lYW4iLCBzaXplID0gKDEvVlpyKSArIDMpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjIpICsgCiAgIyBwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwoKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoc2l6ZT0zLCBzaGFwZT0yMSwgZmlsbCA9ICJibGFjayIpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAwLjkzLCB5ID0gMS4xNSwgbGFiZWw9cGFzdGUoIml0YWxpYyhrKT09IiwgbGVuZ3RoKGRhdCRacikpLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXIpIikpICkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMC42LCB5bWF4ID0gMS4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikKI2dnc2F2ZShwbG90ID0gZmlnX21hLCBmaWxlbmFtZSA9ICJmaWdfMmEucGRmIiwgaGVpZ2h0ID0gMiwgd2lkdGggPSA4KQojIGdncGxvdHkgMCBkb2VzIG5vdCB3b3JrIChFcnJvciBpbiB1bmlxdWUuZGVmYXVsdCh4KSA6IHVuaW1wbGVtZW50ZWQgdHlwZSAnZXhwcmVzc2lvbicgaW4gJ0hhc2hUYWJsZVNldHVwJykKZmlnX21hCgojIGZvciBGaWcgMwoKYSA8LSBnZ3Bsb3QoZGF0YSA9IGVmZmVjdF9tYSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9ICJPdmVyYWxsIG1lYW4iKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCwgYWVzKHg9IHRhbmgoWnIpLCB5ID0gIk92ZXJhbGwgbWVhbiIsIHNpemUgPSAoMS9WWnIpICsgMyksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuMikgKyAKICAjIHByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyBDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCgogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChzaXplPTMsIHNoYXBlPTIxLCBmaWxsID0gImJsYWNrIikgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSAxLjE1LCBsYWJlbD1wYXN0ZSgiaXRhbGljKGspPT0iLCBsZW5ndGgoZGF0JFpyKSksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9ICIiLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSAsdGFnID0gImEiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wYXJhc2l0aXNtKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gMC42LCB5bWF4ID0gMS4yKQoKYGBgCgoqKkZpZ3VyZSAzYToqKiBBbiBvcmNoYXJkIHBsb3QgIHNob3dpbmcgdGhlIG1ldGEtYW5hbHl0aWMgbWVhbiAobWVhbiBlZmZlY3Qgc2l6ZSkgd2l0aCBpdHMgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgKHRoaWNrIGxpbmUpIGFuZCA5NSUgcHJlZGljdGlvbiBpbnRlcnZhbCAodGhpbiBsaW5lKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuICAKCiMjIEFwcGVuZGl4IFMzOiBNZXRhLXJlZ3Jlc3Npb24KCldlIHJhbiBhIHVuaXZhcmlhdGUgbWV0YS1yZWdyZXNzaW9uIG1vZGVsIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgbW9kZXJhdG9yczogMSkgYHN5bWJpb3Npc2AsIDIpIGBob3N0X3RheF9icm9hZGAsIDMpIGBzeW1iaW9udF90YXhfYnJvYWRgLCA0KSBgaG9zdF9yYW5nZV9saW5rX3JhdGlvYCwgNSkgYGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGhgLCA2KSBgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBhbmQgNykgYGVuZG9fb3JfZWN0b2AuIFRoZSByZXN1bHRzIGZyb20gdGhlc2UgbW9kZWxzIGFyZSBwcmVzZW50ZWQgaW4gdGhlIG1haW4gdGV4dC4gCgpJbiBhZGRpdGlvbiB0byB0aGVzZSwgd2UgcmFuIHRocmVlIG1vcmUgdW5pdmFyaWF0ZSBtb2RlbHM6IDEpIGBob3N0X3RheF9zeW1iaW9zaXNgIChlcXVpdmFsZW50IHRvIHRoZSBpbnRlcmFjdGlvbiB0ZXJtIGJldHdlZW4gYHN5bWJpb3Npc2AgYW5kIGBob3N0X3RheF9zeW1iaW9zaXNgOyBgc3ltYmlvc2lzKmhvc3RfdGF4X3N5bWJpb3Npc2ApLCAyKSBgc3ltYmlvbnRfdGF4X3N5bWJpb3Npc2AgKGBzeW1iaW9zaXMqc3ltYmlvbnRfdGF4X2Jyb2FkYCksICAzKSBgaG9zdF9zeW1iaW9udF90YXhgIChgaG9zdF90YXhfc3ltYmlvc2lzKnN5bWJpb250X3RheF9icm9hZGApIGFuZCA0KSBgc3ltYmlvc2lzX3RyYW5zbWlzc2lvbmAgKGBzeW1iaW9zaXMqbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgKS4gVGhlc2UgbW9kZXJhdG9ycyBhcmUgY3JlYXRlZCBiZWxvdzoKCmBgYHtyfQpkYXQgJTw+JSAKICAgICMgaG9zdF90YXhfYnJvYWQqc3ltYmlvc2lzIChob3N0X3RheF9zeW1iaW9zaXMpIAogIG11dGF0ZShob3N0X3RheF9zeW1iaW9zaXMgPSBzdHJfYyhob3N0X3RheF9icm9hZCwgc3ltYmlvc2lzKSwgCiAgICAgICAgIGhvc3RfdGF4X3N5bWJpb3NpcyA9IGlmZWxzZShob3N0X3RheF9zeW1iaW9zaXMgPT0gIkludmVydE5BIiwgTkEsIGhvc3RfdGF4X3N5bWJpb3NpcyksCiAgICAgICAgIGhvc3RfdGF4X3N5bWJpb3NpcyA9IGZhY3Rvcihob3N0X3RheF9zeW1iaW9zaXMpLAogICAgICAgICAjIHN5bWJpb250X3RheF9icm9hZCpzeW1iaW9zaXMgKHN5bWJpb250X3RheF9zeW1iaW9zaXMpICAgICAKICAgICAgICAgc3ltYmlvbnRfdGF4X3N5bWJpb3NpcyA9IGZhY3RvcihzdHJfYyhzeW1iaW9udF90YXhfYnJvYWQsIHN5bWJpb3NpcykpLAogICAgICAgICAjIGhvc3RfdGF4X2Jyb2FkKnN5bWJpb250X3RheF9icm9hZCAoaG9zdF9zeW1iaW9udF90YXgpICAgICAKICAgICAgICAgaG9zdF9zeW1iaW9udF90YXggID0gZmFjdG9yKHN0cl9jKGhvc3RfdGF4X2Jyb2FkLCBzeW1iaW9udF90YXhfYnJvYWQpKSwKICAgICAgICAgIyBzeW1iaW9zaXMqbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKHN5bWJpb3Npc190cmFuc21pc3Npb24pCiAgICAgICAgIHN5bWJpb3Npc190cmFuc21pc3Npb24gID0gZmFjdG9yKHN0cl9jKHN5bWJpb3NpcywgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpKSwKICAgICAgICAgIyB3aGV0aGVyIHAgdmFsdWVzIHdlcmUgdGhlIHNtYWxsZXN0IHZhbHVlIGdpdmVuIHRoZSBudW1iZXIgb2YgcmFuZGFtaXphdGlvbiAtIGxpbWl0X3Jlc2VhcmNoZWQgKFllcyA9IDEsIE5vID0gMCkKICAgICAgICAgbGltaXRfcmVhY2hlZCA9IGlmX2Vsc2UoYWJzKCgxL3BfdmFsdWUpIC0gbm9fcmFuZG9taXphdGlvbnMpIDw9IDEsIDEsIDApKQoKYGBgCgojIyMgVW5pdmFyaWF0ZSAodW5pLXByZWRpY3RvcikgYW5hbHlzZXMKCldlIGZpcnN0IGNvbmR1Y3RlZCBhIHNlcmllcyBvZiBtZXRhLXJlZ3Jlc3Npb24gbW9kZWxzIHdpdGggZWFjaCBvZiB0aGUgbW9kZXJhdG9ycyBpbnRyb2R1Y2VkIGFib3ZlLiAKCiMjIyMgVGhlIHR5cGUgb2Ygc3ltYmlvc2lzOiBwYXJhc2l0aXNtIHZzLiBtdXR1YWxpc20KCmBgYHtyfQojIG1ldGEtcmVncmVzc2lvbjogbXV0aXBsZSBpbnRlcmNlcHRzCm1yX3N5bWJpb3NpczEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3NpcyAtIDEsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0Cm1yX3N5bWJpb3NpczIgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQpgYGAKCiMjIyMgVGFibGUgUzMuMQpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiBbQG5ha2FnYXdhMjAxM2dlbmVyYWxdIChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHN5bWJpb3Npc2AuIE5vdGUgdGhhdCBgbXVgIG1lYW5zIHRoZSBncm91cCBtZWFuIHdoaWxlIGBiZXRhYCByZXByZXNlbnRzIHRoZSBjb250cmFzdCBiZXR3ZWVuIHR3byBncm91cHMgaW4gdGhlIFVuaXQgY29sdW1uLgoKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zeW1iaW9zaXMxIDwtIFIyKG1yX3N5bWJpb3NpczEpCgojIGdldHRpbmcgZXN0aW1hdGVzYGAKcmVzX3N5bWJpb3NpczEgPC0gZ2V0X2VzdChtcl9zeW1iaW9zaXMxLCBtb2QgPSAic3ltYmlvc2lzIikKcmVzX3N5bWJpb3NpczIgPC0gZ2V0X2VzdChtcl9zeW1iaW9zaXMyLCBtb2QgPSAic3ltYmlvc2lzIikKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKHJlcChhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb3NpczEkbmFtZSksMiksIGNvbnRfZ2VuKHJlc19zeW1iaW9zaXMxJG5hbWUpKSwKICBgVW5pdGAgPSBjKHJlcChjKCJaciAobXUpIiwgInIgKG11KSIpLGVhY2ggPSAyKSwgIlpyIChiZXRhKSIpLAogIEVzdGltYXRlID0gYyhyZXNfc3ltYmlvc2lzMSRlc3RpbWF0ZSwgdGFuaChyZXNfc3ltYmlvc2lzMSRlc3RpbWF0ZSksIHJlc19zeW1iaW9zaXMyJGVzdGltYXRlWzJdKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19zeW1iaW9zaXMxJGxvd2VyQ0wsIHRhbmgocmVzX3N5bWJpb3NpczEkbG93ZXJDTCksIHJlc19zeW1iaW9zaXMyJGxvd2VyQ0xbMl0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19zeW1iaW9zaXMxJHVwcGVyQ0wsIHRhbmgocmVzX3N5bWJpb3NpczEkdXBwZXJDTCksIHJlc19zeW1iaW9zaXMyJHVwcGVyQ0xbMl0pLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfc3ltYmlvc2lzMSRzaWdtYTIsICByZXAoTkEsIDQpKSwKICBgUjJgID0gYyhyMl9zeW1iaW9zaXMxWzFdLCByZXAoTkEsIDQpKSkgLT4gdF9zeW1iaW9zaXMKdF9zeW1iaW9zaXMgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCiMjIyMgRmlndXJlIDNiIAoKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0yLjV9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX3N5bWJpb3NpcyA8LSBkYXQgJT4lIGdyb3VwX2J5KHN5bWJpb3NpcykgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9zeW1iaW9zaXMgPC0gZ2V0X3ByZWQobXJfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb3NpcyIpIApyZXNfc3ltYmlvc2lzMSA8LSBsZWZ0X2pvaW4ocmVzX3N5bWJpb3NpczEsIGtfc3ltYmlvc2lzLCBieSA9ICBjKCJuYW1lIiA9ICJzeW1iaW9zaXMiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9zeW1iaW9zaXMpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX3N5bWJpb3NpcyA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19zeW1iaW9zaXMxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvc2lzKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvc2lzLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gc3ltYmlvc2lzKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC4yKSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTXV0dWFsaXN0IiA9ICIjRTY5RjAwIiwgIlBhcmFzaXRlIiA9ICIjNTZCNEU5IikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNdXR1YWxpc3QiID0gIiNFNjlGMDAiLCAiUGFyYXNpdGUiID0gIiM1NkI0RTkiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSBjKDEuMTUsIDIuMTUpLCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb3NpczEkbiksIHBhcnNlID0gVFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemUgPSAzLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BhcmFzaXRpc20pLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKQoKZmlnX3N5bWJpb3NpcwoKIyBmaWcgMwoKYiA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19zeW1iaW9zaXMxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvc2lzKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gc3ltYmlvc2lzLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gc3ltYmlvc2lzKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC4yKSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTXV0dWFsaXN0IiA9ICIjRTY5RjAwIiwgIlBhcmFzaXRlIiA9ICIjNTZCNEU5IikpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNdXR1YWxpc3QiID0gIiNFNjlGMDAiLCAiUGFyYXNpdGUiID0gIiM1NkI0RTkiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSBjKDEuMTUsIDIuMTUpLCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb3NpczEkbiksIHBhcnNlID0gVFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemUgPSAzLjUpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiLCB0YWcgPSAiYiIpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BhcmFzaXRpc20pLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKQpgYGAKCioqRmlndXJlIDNiOioqIEFuIG9yY2hhcmQgcGxvdCBzaG93aW5nIHRoZSBncm91cC13aXNlIG1lYW5zICh0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgYHN5bWJpb3Npc2ApIHdpdGggdGhlaXIgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzICh0aGljayBsaW5lcykgYW5kIDk1JSBwcmVkaWN0aW9uIGludGVydmFscyAodGhpbiBsaW5lcyksIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLiAgCgoKIyMjIyBUaGUgZWZmZWN0IG9mIGhvc3QgdGF4YQoKYGBge3J9CiMgcmVvcmRlcmluZwpkYXQkaG9zdF90YXhfYnJvYWQgPC0gZmFjdG9yKGRhdCRob3N0X3RheF9icm9hZCwgbGV2ZWxzID0gYygiTWljcm9iZSIsICJQbGFudCIsICJJbnZlcnQiLCAiVmVydCIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9ob3N0X3RheF9icm9hZDEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IGhvc3RfdGF4X2Jyb2FkIC0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0IDEKbXJfaG9zdF90YXhfYnJvYWQyIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBob3N0X3RheF9icm9hZCwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0IDIKbXJfaG9zdF90YXhfYnJvYWQzIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiByZWxldmVsKGhvc3RfdGF4X2Jyb2FkLCByZWYgPSAiUGxhbnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0IDMKbXJfaG9zdF90YXhfYnJvYWQ0IDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiByZWxldmVsKGhvc3RfdGF4X2Jyb2FkLCByZWYgPSAiSW52ZXJ0IiksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKYGBgCgojIyMjIFRhYmxlIFMzLjIKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKGVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhwbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgaG9zdF90YXhfYnJvYWRgLiAgTm90ZSB0aGF0IGBtdWAgbWVhbnMgdGhlIGdyb3VwIG1lYW4gd2hpbGUgYGJldGFgIHJlcHJlc2VudHMgdGhlIGNvbnRyYXN0IGJldHdlZW4gdHdvIGdyb3VwcyBpbiB0aGUgVW5pdCBjb2x1bW4uCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfaG9zdF90YXhfYnJvYWQxIDwtIFIyKG1yX2hvc3RfdGF4X2Jyb2FkMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX2hvc3RfdGF4X2Jyb2FkMSA8LSBnZXRfZXN0KG1yX2hvc3RfdGF4X2Jyb2FkMSwgbW9kID0gImhvc3RfdGF4X2Jyb2FkIikKcmVzX2hvc3RfdGF4X2Jyb2FkMiA8LSBnZXRfZXN0KG1yX2hvc3RfdGF4X2Jyb2FkMiwgbW9kID0gImhvc3RfdGF4X2Jyb2FkIikKIyB0aGUgbmFtZSBiaXQgZG9lcyBub3Qgd29yayBpZiByZWxldmVsLi4uLgpyZXNfaG9zdF90YXhfYnJvYWQzIDwtIGdldF9lc3QobXJfaG9zdF90YXhfYnJvYWQzLCBtb2QgPSAiaG9zdF90YXhfYnJvYWQiKQpyZXNfaG9zdF90YXhfYnJvYWQ0IDwtIGdldF9lc3QobXJfaG9zdF90YXhfYnJvYWQ0LCBtb2QgPSAiaG9zdF90YXhfYnJvYWQiKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMocmVwKGFzLmNoYXJhY3RlcihyZXNfaG9zdF90YXhfYnJvYWQxJG5hbWUpLDIpLCBjb250X2dlbihyZXNfaG9zdF90YXhfYnJvYWQxJG5hbWUpKSwKICBgVW5pdGAgPSBjKHJlcChjKCJaciAobXUpIiwgInIgKG11KSIpLGVhY2ggPSA0KSwgcmVwKCJaciAoYmV0YSkiLCA2KSksCiAgRXN0aW1hdGUgPSBjKHJlc19ob3N0X3RheF9icm9hZDEkZXN0aW1hdGUsIHRhbmgocmVzX2hvc3RfdGF4X2Jyb2FkMSRlc3RpbWF0ZSksIHJlc19ob3N0X3RheF9icm9hZDIkZXN0aW1hdGVbLTFdLCAgcmVzX2hvc3RfdGF4X2Jyb2FkMyRlc3RpbWF0ZVstKDE6MildLCByZXNfaG9zdF90YXhfYnJvYWQ0JGVzdGltYXRlWy0oMTozKV0pLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2hvc3RfdGF4X2Jyb2FkMSRsb3dlckNMLCB0YW5oKHJlc19ob3N0X3RheF9icm9hZDEkbG93ZXJDTCksIHJlc19ob3N0X3RheF9icm9hZDIkbG93ZXJDTFstMV0sIHJlc19ob3N0X3RheF9icm9hZDMkbG93ZXJDTFstKDE6MildLCByZXNfaG9zdF90YXhfYnJvYWQ0JGxvd2VyQ0xbLSgxOjMpXSksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX2hvc3RfdGF4X2Jyb2FkMSR1cHBlckNMLCB0YW5oKHJlc19ob3N0X3RheF9icm9hZDEkdXBwZXJDTCksIHJlc19ob3N0X3RheF9icm9hZDIkdXBwZXJDTFstMV0sIHJlc19ob3N0X3RheF9icm9hZDMkdXBwZXJDTFstKDE6MildLCByZXNfaG9zdF90YXhfYnJvYWQ0JHVwcGVyQ0xbLSgxOjMpXSksCiAgYFZbYXV0aG9yc11gID0gYyhtcl9ob3N0X3RheF9icm9hZDEkc2lnbWEyLCAgcmVwKE5BLCAxMykpLAogIGBSMmAgPSBjKHIyX2hvc3RfdGF4X2Jyb2FkMVsxXSwgcmVwKE5BLCAxMykpKSAtPiB0X2hvc3RfdGF4Cgp0X2hvc3RfdGF4ICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikKYGBgCiMjIyMgRmlndXJlIDNjCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gNH0KIyBnZXR0aW5nIGltYWdlcwppbWFnZV9pbnZlcnRlYnJhdGVfaG9zdCA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9pbnZlcnRlYnJhdGVfaG9zdF90cmFuc3BhcmVudGJnLnBuZyIpKQppbWFnZV9taWNyb2JlX2hvc3QgPC0gcmVhZFBORyhoZXJlKCJpbWFnZXMvbWljcm9iZV9ob3N0X3RyYW5zcGFyZW50YmcucG5nIikpCmltYWdlX3ZlcnRlYnJhdGVfaG9zdCA8LSByZWFkUE5HKGhlcmUoImltYWdlcy92ZXJ0ZWJyYXRlX2hvc3RfdHJhbnNwYXJlbnRiZy5wbmciKSkKaW1hZ2VfcGxhbnRfaG9zdCA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9wbGFudF9ob3N0X3RyYW5zcGFyZW50YmcucG5nIikpCgojIGFkZGluZyBzYW1wbGUgc2l6ZSAoaykgZm9yIGVhY2ggY2F0ZWdvcnkKa19ob3N0X3RheF9icm9hZCA8LSBkYXQgJT4lIGdyb3VwX2J5KGhvc3RfdGF4X2Jyb2FkKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX2hvc3RfdGF4X2Jyb2FkIDwtIGdldF9wcmVkKG1yX2hvc3RfdGF4X2Jyb2FkMSwgbW9kID0gImhvc3RfdGF4X2Jyb2FkIikgCnJlc19ob3N0X3RheF9icm9hZDEgPC0gbGVmdF9qb2luKHJlc19ob3N0X3RheF9icm9hZDEsIGtfaG9zdF90YXhfYnJvYWQsIGJ5ID0gIGMoIm5hbWUiID0gImhvc3RfdGF4X2Jyb2FkIikpICAlPiUgbGVmdF9qb2luKHByZWRfaG9zdF90YXhfYnJvYWQpCiNyZXNfc3ltYmlvc2lzMSAKIyBkcmF3aW5nIGEgZnVubmVsIHBsb3QgLSBmaWcgMmIKZmlnX2hvc3RfdGF4X2Jyb2FkIDwtIGdncGxvdChkYXRhID0gcmVzX2hvc3RfdGF4X2Jyb2FkMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gaG9zdF90YXhfYnJvYWQsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBob3N0X3RheF9icm9hZCksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmUiID0gIiMwMDlFNzMiLCAgIlBsYW50IiA9ICIjRjBFNDIyIiwgICJJbnZlcnQiPSAiIzAwNzJCMiIsICAiVmVydCIgPSAiI0Q1NUUwMCIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZSIgPSAiIzAwOUU3MyIsICAiUGxhbnQiID0gIiNGMEU0MjIiLCAgIkludmVydCI9ICIjMDA3MkIyIiwgICJWZXJ0IiA9ICIjRDU1RTAwIikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmUiID0gIk1pY3JvYmUiLCAgIlBsYW50IiA9ICJQbGFudCIsICAiSW52ZXJ0Ij0gIkludmVydGVicmF0ZSIsICAiVmVydCIgPSAiVmVydGVicmF0ZSIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9IDE6NCArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF90YXhfYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9ob3N0KSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BsYW50X2hvc3QpLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9pbnZlcnRlYnJhdGVfaG9zdCksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMy42LCB5bWF4ID0gNC4yKQoKZmlnX2hvc3RfdGF4X2Jyb2FkCgojIGZpZyAzYwpjIDwtIGdncGxvdChkYXRhID0gcmVzX2hvc3RfdGF4X2Jyb2FkMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gaG9zdF90YXhfYnJvYWQsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBob3N0X3RheF9icm9hZCksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmUiID0gIiMwMDlFNzMiLCAgIlBsYW50IiA9ICIjRjBFNDIyIiwgICJJbnZlcnQiPSAiIzAwNzJCMiIsICAiVmVydCIgPSAiI0Q1NUUwMCIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZSIgPSAiIzAwOUU3MyIsICAiUGxhbnQiID0gIiNGMEU0MjIiLCAgIkludmVydCI9ICIjMDA3MkIyIiwgICJWZXJ0IiA9ICIjRDU1RTAwIikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmUiID0gIk1pY3JvYmUiLCAgIlBsYW50IiA9ICJQbGFudCIsICAiSW52ZXJ0Ij0gIkludmVydGVicmF0ZSIsICAiVmVydCIgPSAiVmVydGVicmF0ZSIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9IDE6NCArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF90YXhfYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSkgLCB0YWcgPSAiYyIpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9ob3N0KSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BsYW50X2hvc3QpLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9pbnZlcnRlYnJhdGVfaG9zdCksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEsIHhtYXggPSAtMC44LCB5bWluID0gMy42LCB5bWF4ID0gNC4yKQpgYGAKCioqRmlndXJlIDNjOioqIEFuIG9yY2hhcmQgcGxvdCBzaG93aW5nIHRoZSBncm91cC13aXNlIG1lYW5zICh0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgYGhvc3RfdGF4X2Jyb2FkYCkgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKHRoaWNrIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzICh0aGluIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuICAKCiMjIyMgVGhlIGVmZmVjdCBvZiBzeW1iaW9udCB0YXhhCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9udF90YXhfYnJvYWQgPC0gZmFjdG9yKGRhdCRzeW1iaW9udF90YXhfYnJvYWQsIGxldmVscyA9IGMoIk1pY3JvYmUiLCAiUGxhbnQiLCAiSW52ZXJ0IiwgIlZlcnQiKSkKCiNzaXplcyA8LSBmYWN0b3Ioc2l6ZXMsIGxldmVscyA9IGMoInNtYWxsIiwgIm1lZGl1bSIsICJsYXJnZSIpKQojc2l6ZXMKIz4gWzFdIHNtYWxsICBsYXJnZSAgbGFyZ2UgIHNtYWxsICBtZWRpdW0KIz4gTGV2ZWxzOiBzbWFsbCBtZWRpdW0gbGFyZ2UKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9zeW1iaW9udF90YXhfYnJvYWQxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzeW1iaW9udF90YXhfYnJvYWQgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9zeW1iaW9udF90YXhfYnJvYWQyIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzeW1iaW9udF90YXhfYnJvYWQsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdCAyCm1yX3N5bWJpb250X3RheF9icm9hZDMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvbnRfdGF4X2Jyb2FkLCByZWYgPSAiUGxhbnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQoKIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0IDMKbXJfc3ltYmlvbnRfdGF4X2Jyb2FkNCA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gcmVsZXZlbChzeW1iaW9udF90YXhfYnJvYWQsIHJlZiA9ICJJbnZlcnQiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCAKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZGF0KQpgYGAKCiMjIyMgVGFibGUgUzMuMwpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfYnJvYWRgLiAgTm90ZSB0aGF0IGBtdWAgbWVhbnMgdGhlIGdyb3VwIG1lYW4gd2hpbGUgYGJldGFgIHJlcHJlc2VudHMgdGhlIGNvbnRyYXN0IGJldHdlZW4gdHdvIGdyb3VwcyBpbiB0aGUgVW5pdCBjb2x1bW4uCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc3ltYmlvbnRfdGF4X2Jyb2FkMSA8LSBSMihtcl9zeW1iaW9udF90YXhfYnJvYWQxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDEsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMiA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDIsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDMsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQpyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkNCA8LSBnZXRfZXN0KG1yX3N5bWJpb250X3RheF9icm9hZDQsIG1vZCA9ICJzeW1iaW9udF90YXhfYnJvYWQiKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJG5hbWUpLGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lKSwgY29udF9nZW4ocmVzX3N5bWJpb250X3RheF9icm9hZDEkbmFtZSkpLAogIGBVbml0YCA9IGMocmVwKGMoIlpyIChtdSkiLCAiciAobXUpIiksZWFjaCA9IDQpLCByZXAoIlpyIChiZXRhKSIsIDYpKSwKICBFc3RpbWF0ZSA9IGMocmVzX3N5bWJpb250X3RheF9icm9hZDEkZXN0aW1hdGUsIHRhbmgocmVzX3N5bWJpb250X3RheF9icm9hZDEkZXN0aW1hdGUpLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMiRlc3RpbWF0ZVstMV0sICByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyRlc3RpbWF0ZVstKDE6MildLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkNCRlc3RpbWF0ZVstKDE6MyldKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJGxvd2VyQ0wsIHRhbmgocmVzX3N5bWJpb250X3RheF9icm9hZDEkbG93ZXJDTCksIHJlc19zeW1iaW9udF90YXhfYnJvYWQyJGxvd2VyQ0xbLTFdLCByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMyRsb3dlckNMWy0oMToyKV0sIHJlc19zeW1iaW9udF90YXhfYnJvYWQ0JGxvd2VyQ0xbLSgxOjMpXSksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3N5bWJpb250X3RheF9icm9hZDEkdXBwZXJDTCwgdGFuaChyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSR1cHBlckNMKSwgcmVzX3N5bWJpb250X3RheF9icm9hZDIkdXBwZXJDTFstMV0sIHJlc19zeW1iaW9udF90YXhfYnJvYWQzJHVwcGVyQ0xbLSgxOjIpXSwgcmVzX3N5bWJpb250X3RheF9icm9hZDQkdXBwZXJDTFstKDE6MyldKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX3N5bWJpb250X3RheF9icm9hZDEkc2lnbWEyLCAgcmVwKE5BLCAxMykpLAogIGBSMmAgPSBjKHIyX3N5bWJpb250X3RheF9icm9hZDFbMV0sIHJlcChOQSwgMTMpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQpgYGAKIyMjIyBGaWd1cmUgM2QKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQojIGdldHRpbmcgaW1hZ2VzCmltYWdlX2ludmVydGVicmF0ZV9wYXJhc2l0ZSA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9pbnZlcnRlYnJhdGVfcGFyYXNpdGVfdHJhbnNwYXJlbnRiZy5wbmciKSkKaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9taWNyb2JlX3BhcmFzaXRlX3RyYW5zcGFyZW50YmcucG5nIikpCmltYWdlX3ZlcnRlYnJhdGVfcGFyYXNpdGUgPC0gcmVhZFBORyhoZXJlKCJpbWFnZXMvdmVydGVicmF0ZV9wYXJhc2l0ZV90cmFuc3BhcmVudGJnLnBuZyIpKQppbWFnZV9wbGFudF9wYXJhc2l0ZSA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9wbGFudF9wYXJhc2l0ZV90cmFuc3BhcmVudGJnLnBuZyIpKQoKIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5Cmtfc3ltYmlvbnRfdGF4X2Jyb2FkIDwtIGRhdCAlPiUgZ3JvdXBfYnkoc3ltYmlvbnRfdGF4X2Jyb2FkKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX3N5bWJpb250X3RheF9icm9hZCA8LSBnZXRfcHJlZChtcl9zeW1iaW9udF90YXhfYnJvYWQxLCBtb2QgPSAic3ltYmlvbnRfdGF4X2Jyb2FkIikgCnJlc19zeW1iaW9udF90YXhfYnJvYWQxIDwtIGxlZnRfam9pbihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSwga19zeW1iaW9udF90YXhfYnJvYWQsIGJ5ID0gIGMoIm5hbWUiID0gInN5bWJpb250X3RheF9icm9hZCIpKSAgJT4lIGxlZnRfam9pbihwcmVkX3N5bWJpb250X3RheF9icm9hZCkKI3Jlc19zeW1iaW9zaXMxIAojIGRyYXdpbmcgYSBmdW5uZWwgcGxvdCAtIGZpZyAyYgpmaWdfc3ltYmlvbnRfdGF4X2Jyb2FkIDwtIGdncGxvdChkYXRhID0gcmVzX3N5bWJpb250X3RheF9icm9hZDEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShzeW1iaW9udF90YXhfYnJvYWQpKSwgCiAgICAgICAgICAgICAgICAgICBhZXMoeD0gdGFuaChaciksIHkgPSBzeW1iaW9udF90YXhfYnJvYWQsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBzeW1iaW9udF90YXhfYnJvYWQpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJNaWNyb2JlIiA9ICIjMDA5RTczIiwgICJQbGFudCIgPSAiI0YwRTQyMiIsICAiSW52ZXJ0Ij0gIiMwMDcyQjIiLCAgIlZlcnQiID0gIiNENTVFMDAiICkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNaWNyb2JlIiA9ICIjMDA5RTczIiwgICJQbGFudCIgPSAiI0YwRTQyMiIsICAiSW52ZXJ0Ij0gIiMwMDcyQjIiLCAgIlZlcnQiID0gIiNENTVFMDAiKSkgKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiTWljcm9iZSIgPSAiTWljcm9iZSIsICAiUGxhbnQiID0gIlBsYW50IiwgICJJbnZlcnQiPSAiSW52ZXJ0ZWJyYXRlIiwgICJWZXJ0IiA9ICJWZXJ0ZWJyYXRlIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAwLjkzLCB5ID0gMTo0ICsgMC4xNSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19zeW1iaW9udF90YXhfYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wbGFudF9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2ludmVydGVicmF0ZV9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikKCmZpZ19zeW1iaW9udF90YXhfYnJvYWQKCiMgZmlnIDNkCmQgPC0gZ2dwbG90KGRhdGEgPSByZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKHN5bWJpb250X3RheF9icm9hZCkpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IHN5bWJpb250X3RheF9icm9hZCwgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IHN5bWJpb250X3RheF9icm9hZCksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmUiID0gIiMwMDlFNzMiLCAgIlBsYW50IiA9ICIjRjBFNDIyIiwgICJJbnZlcnQiPSAiIzAwNzJCMiIsICAiVmVydCIgPSAiI0Q1NUUwMCIgKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIk1pY3JvYmUiID0gIiMwMDlFNzMiLCAgIlBsYW50IiA9ICIjRjBFNDIyIiwgICJJbnZlcnQiPSAiIzAwNzJCMiIsICAiVmVydCIgPSAiI0Q1NUUwMCIpKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJNaWNyb2JlIiA9ICJNaWNyb2JlIiwgICJQbGFudCIgPSAiUGxhbnQiLCAgIkludmVydCI9ICJJbnZlcnRlYnJhdGUiLCAgIlZlcnQiID0gIlZlcnRlYnJhdGUiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSAxOjQgKyAwLjE1LCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb250X3RheF9icm9hZDEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdGlvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpLCB0YWcgPSAiZCIpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wbGFudF9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2ludmVydGVicmF0ZV9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikKCmBgYAoKKipGaWd1cmUgM2Q6KiogQW4gb3JjaGFyZCBwbG90IHNob3dpbmcgdGhlIGdyb3VwLXdpc2UgbWVhbnMgKHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBgc3ltYmlvbnRfdGF4X2Jyb2FkYCkgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKHRoaWNrIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzICh0aGluIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuICAKCgojIyMjIFRlc3Rpbmcgc3BlY2lhbGl6YXRpb24gMTogaG9zdCByYW5nZQoKYGBge3J9CiMgbWV0YS1yZWdyZXNzaW9uCm1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgbW9kcyA9IH4gbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbyksIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCiMjIyMgVGFibGUgUzMuNApSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKWAuICBOb3RlIHRoYXQgYG11YCBzaG93cyB0aGUgb3ZlcmFsbCB3aGlsZSBgYmV0YWAgcmVwcmVzZW50cyBhIHNsb3BlIGluIHRoZSBVbml0IGNvbHVtbi4KYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8gPC0gUjIobXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvKQoKIyBnZXR0aW5nIGVzdGltYXRlczogbmFtZSBkb2VzIG5vdCB3b3JrIGZvciBzbG9wZXMKcmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyA8LSBnZXRfZXN0KG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbywgbW9kID0gImxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pIikKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKCJJbnRlcmNlcHQiLCAiSW50ZXJjZXB0IiwgImxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pIiksCiAgYFVuaXRgID0gYyhyZXAoYygiWnIgKG11KSIsICJyIChtdSkiKSwxKSwgcmVwKCJaciAoYmV0YSkiLCAxKSksCiAgRXN0aW1hdGUgPSBjKHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kZXN0aW1hdGVbMV0sIHRhbmgocmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRlc3RpbWF0ZVsxXSksIHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kZXN0aW1hdGVbMl0pLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRsb3dlckNMWzFdLCB0YW5oKHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kbG93ZXJDTFsxXSksIHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kbG93ZXJDTFsyXSksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyR1cHBlckNMWzFdLCB0YW5oKHJlc19ob3N0X3JhbmdlX2xpbmtfcmF0aW8kdXBwZXJDTFsxXSkscmVzX2hvc3RfcmFuZ2VfbGlua19yYXRpbyR1cHBlckNMWzJdKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRzaWdtYTIsIE5BLCBOQSksCiAgYFIyYCA9IGMocjJfaG9zdF9yYW5nZV9saW5rX3JhdGlvWzFdLCBOQSwgTkEpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQojIG5ld21vZHMgPC0gc2VxKC0wLjMsIDIuMiwgYnkgPSAwLjEpCiMgcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8gPC1wcmVkaWN0LnJtYShtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8sIG5ld21vZHMgPSBuZXdtb2RzKSAKIyByaWJib25fZGF0IDwtIHRpYmJsZShuZXdtb2RzID0gbmV3bW9kcywgeW1pbiA9IHByZWRfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGNpLmxiLCB5bWF4ID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY2kudWIpCnByZWRfaG9zdF9yYW5nZV9saW5rX3JhdGlvIDwtcHJlZGljdC5ybWEobXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvKSAKCiMgcGxvdHRpbmcKCmZpZ19ob3N0X3JhbmdlX2xpbmtfcmF0aW8gPC0gIGRhdCAlPiUgCiAgZmlsdGVyKCFpcy5uYShob3N0X3JhbmdlX2xpbmtfcmF0aW8pKSAgJT4lICMgZ2V0dGluZyByaWRlIG9mIE5BIHZhbHVlcwogIG11dGF0ZSh5bWluID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY2kubGIsIAogICAgICAgICB5bWF4ID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY3IubGIsCiAgICAgICAgIHltYXgyID0gcHJlZF9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kY3IudWIsCiAgICAgICAgIHByZWQgPSBwcmVkX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbyksIHkgPSBaciwgc2l6ZSA9ICgxL1ZacikgKyAzLCApKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gImdyZXk5MCIpICsKICAjZ2VvbV9yaWJib24oYWVzKHltaW4gPSB5bWluLCB5bWF4ID0geW1heCksIGZpbGwgPSAiIzAwNzJCMiIpICArICMgbm90IHF1aXRlIHN1cmUgd2h5IHRoaXMgZG9lcyBub3Qgd29yawogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbjIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgyKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4pLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSxsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsgCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBwcmVkKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRhc2hlZCIsIGx3ZCA9IDAuNSwgY29sb3VyID0iYmxhY2siKSArICAKICB5bGltKC0xLCAyKSArIHhsaW0oLTAuMDUsIDIpICsKICAjZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzFdXSwgc2xvcGUgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMl1dLCBhbHBoYSA9IDAuNywgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuNSkgKwogIGxhYnMoeCA9ICJsbihob3N0IHJhbmdlIGxpbmsgcmF0aW8pIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX2hvc3RfcmFuZ2VfbGlua19yYXRpbwpgYGAKCiMjIyMgRmlndXJlIFMzLjEgCkEgYnViYmxlIHBsb3Qgc2hvd2luZyBhIHByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlIGBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKWAsIGluZGljYXRpbmcgOTUlIGNvbmZpZGVuY2UgcmVnaW9ucyAob3JhbmdlIGRvdHRlZCBsaW5lcykgYW5kIDk1JSBwcmVkaWN0aW9uIHJlZ2lvbnMgKGJsdWUgZG90dGVkIGxpbmVzKSB3aXRoIG9ic2VydmVkIGVmZmVjdCBzaXplcyBiYXNlZCBvbiB2YXJpb3VzIHNhbXBsZSBzaXplcy4gCgoKIyMjIyBUZXN0aW5nIHNwZWNpYWxpemF0aW9uIDI6IHRheG9ub21pYyBicmVhZHRoCgpgYGB7cn0KIyBtZXRhLXJlZ3Jlc3Npb24KbXJfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgbW9kcyA9IH4gbG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpLCByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBkYXRhID0gZGF0KQoKYGBgCgojIyMjIFRhYmxlIFMzLjUKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhwbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgbG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpYC4gIE5vdGUgdGhhdCBgbXVgIHNob3dzIHRoZSBvdmVyYWxsIHdoaWxlIGBiZXRhYCByZXByZXNlbnRzIGEgc2xvcGUgaW4gdGhlIFVuaXQgY29sdW1uLgpgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGggPC0gUjIobXJfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCkKCiMgZ2V0dGluZyBlc3RpbWF0ZXM6IG5hbWUgZG9lcyBub3Qgd29yayBmb3Igc2xvcGVzCnJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoIDwtIGdldF9lc3QobXJfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCwgbW9kID0gImxvZyhob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKSIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYygiSW50ZXJjZXB0IiwiSW50ZXJjZXB0IiwgImxvZyhob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKSIpLAogIGBVbml0YCA9IGMocmVwKGMoIlpyIChtdSkiLCAiciAobXUpIiksMSksIHJlcCgiWnIgKGJldGEpIiwgMSkpLAogIEVzdGltYXRlID0gYyhyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRlc3RpbWF0ZVsxXSx0YW5oKHJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJGVzdGltYXRlWzFdKSAscmVzX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgkZXN0aW1hdGVbMl0pLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgkbG93ZXJDTFsxXSwgdGFuaChyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRsb3dlckNMWzFdKSxyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRsb3dlckNMWzJdKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCR1cHBlckNMWzFdLCB0YW5oKHJlc19ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJHVwcGVyQ0xbMV0pICxyZXNfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCR1cHBlckNMWzJdKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgkc2lnbWEyLCBOQSwgTkEpLAogIGBSMmAgPSBjKHIyX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGhbMV0sIE5BLCBOQSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CnByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCA8LXByZWRpY3Qucm1hKG1yX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpIAoKIyBwbG90dGluZwoKZmlnX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGggPC0gIGRhdCAlPiUgCiAgZmlsdGVyKCFpcy5uYShob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKSkgICU+JSAjIGdldHRpbmcgcmlkZSBvZiBOQSB2YWx1ZXMKICBtdXRhdGUoeW1pbiA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRjaS5sYiwgCiAgICAgICAgIHltYXggPSBwcmVkX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgkY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF9ob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoJGNyLmxiLAogICAgICAgICB5bWF4MiA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRjci51YiwKICAgICAgICAgcHJlZCA9IHByZWRfaG9zdF9yYW5nZV90YXhvbm9taWNfYnJlYWR0aCRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpLCB5ID0gWnIsIHNpemUgPSAoMS9WWnIpICsgMywgKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJncmV5OTAiKSArCiAgI2dlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gIiMwMDcyQjIiKSAgKyAjIG5vdCBxdWl0ZSBzdXJlIHdoeSB0aGlzIGRvZXMgbm90IHdvcmsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4yKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4MiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4KSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArIAogIGdlb21fc21vb3RoKGFlcyh5ID0gcHJlZCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkYXNoZWQiLCBsd2QgPSAwLjUsIGNvbG91ciA9ImJsYWNrIikgKyAgCiAgeWxpbSgtMSwgMikgKyB4bGltKDAsIDEuNSkgKwogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gImxuKGhvc3QgcmFuZ2UgdGF4b25vbWljIGJyZWFkdGgpIiwgeSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKFpyKSwgIiAoZWZmZWN0IHNpemUpIikpLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSkpICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgIyB0aGVtc2VzCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDEsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMSwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpIAoKZmlnX2hvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgKYGBgCgojIyMjIEZpZ3VyZSBTMy4yCkEgYnViYmxlIHBsb3Qgc2hvd2luZyBhIHByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlIGBsb2cobG9nKGhvc3RfcmFuZ2VfdGF4b25vbWljX2JyZWFkdGgpYCwgaW5kaWNhdGluZyA5NSUgY29uZmlkZW5jZSByZWdpb25zIChvcmFuZ2UgZG90dGVkIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gcmVnaW9ucyAoYmx1ZSBkb3R0ZWQgbGluZXMpIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLiAKCgojIyMjIFN5bWJpb250IGxvY2F0aW9uIG9uIGhvc3Q6IGVuZG9zeW1iaW9zaXMgdnMuIGVjdG9zeW1iaW9zaXMKCmBgYHtyfQojIHJlb3JkZXJpbmcKZGF0JGVuZG9fb3JfZWN0byA8LSBmYWN0b3IoZGF0JGVuZG9fb3JfZWN0bywgbGV2ZWxzID0gYygiRW5kby9FY3RvIiwgIkVuZG8iLCAiRWN0byIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9lbmRvX29yX2VjdG8xIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBlbmRvX29yX2VjdG8gLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9lbmRvX29yX2VjdG8yIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBlbmRvX29yX2VjdG8sIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdCAyCm1yX2VuZG9fb3JfZWN0bzMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoZW5kb19vcl9lY3RvLCByZWYgPSAiRW5kbyIpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgpgYGAKCiMjIyMgVGFibGUgUzMuNgpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoZXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBlbmRvX29yX2VjdG9gLiAgTm90ZSB0aGF0IGBtdWAgbWVhbnMgdGhlIGdyb3VwIG1lYW4gd2hpbGUgYGJldGFgIHJlcHJlc2VudHMgdGhlIGNvbnRyYXN0IGJldHdlZW4gdHdvIGdyb3VwcyBpbiB0aGUgVW5pdCBjb2x1bW4uCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfZW5kb19vcl9lY3RvMSA8LSBSMihtcl9lbmRvX29yX2VjdG8xKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfZW5kb19vcl9lY3RvMSA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzEsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQpyZXNfZW5kb19vcl9lY3RvMiA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzIsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQpyZXNfZW5kb19vcl9lY3RvMyA8LSBnZXRfZXN0KG1yX2VuZG9fb3JfZWN0bzMsIG1vZCA9ICJlbmRvX29yX2VjdG8iKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19lbmRvX29yX2VjdG8xJG5hbWUpLGFzLmNoYXJhY3RlcihyZXNfZW5kb19vcl9lY3RvMSRuYW1lKSwgY29udF9nZW4ocmVzX2VuZG9fb3JfZWN0bzEkbmFtZSkpLAogICBgVW5pdGAgPSBjKHJlcChjKCJaciAobXUpIiwgInIgKG11KSIpLGVhY2ggPSAzKSwgcmVwKCJaciAoYmV0YSkiLCAzKSksCiAgRXN0aW1hdGUgPSBjKHJlc19lbmRvX29yX2VjdG8xJGVzdGltYXRlLCB0YW5oKHJlc19lbmRvX29yX2VjdG8xJGVzdGltYXRlKSwgcmVzX2VuZG9fb3JfZWN0bzIkZXN0aW1hdGVbLTFdLCAgcmVzX2VuZG9fb3JfZWN0bzMkZXN0aW1hdGVbLSgxOjIpXSksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfZW5kb19vcl9lY3RvMSRsb3dlckNMLCB0YW5oKHJlc19lbmRvX29yX2VjdG8xJGxvd2VyQ0wpLCByZXNfZW5kb19vcl9lY3RvMiRsb3dlckNMWy0xXSwgcmVzX2VuZG9fb3JfZWN0bzMkbG93ZXJDTFstKDE6MildKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhyZXNfZW5kb19vcl9lY3RvMSR1cHBlckNMLCB0YW5oKHJlc19lbmRvX29yX2VjdG8xJHVwcGVyQ0wpLCByZXNfZW5kb19vcl9lY3RvMiR1cHBlckNMWy0xXSwgcmVzX2VuZG9fb3JfZWN0bzMkdXBwZXJDTFstKDE6MildKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2VuZG9fb3JfZWN0bzEkc2lnbWEyLCAgcmVwKE5BLCA4KSksCiAgYFIyYCA9IGMocjJfZW5kb19vcl9lY3RvMVsxXSwgcmVwKE5BLCA4KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKIyMjIyBGaWd1cmUgNGEKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQojIGdldHRpbmcgaW1hZ2VzCmltYWdlX2VuZG9wYXJhc2l0ZSA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9lbmRvcGFyYXNpdGVfdHJhbnNwYXJlbnRiZy5wbmciKSkKaW1hZ2VfZWN0b3BhcmFzaXRlIDwtIHJlYWRQTkcoaGVyZSgiaW1hZ2VzL2VjdG9wYXJhc2l0ZV90cmFuc3BhcmVudGJnLnBuZyIpKQoKIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5CmtfZW5kb19vcl9lY3RvIDwtIGRhdCAlPiUgZ3JvdXBfYnkoZW5kb19vcl9lY3RvKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX2VuZG9fb3JfZWN0byA8LSBnZXRfcHJlZChtcl9lbmRvX29yX2VjdG8xLCBtb2QgPSAiZW5kb19vcl9lY3RvIikgCnJlc19lbmRvX29yX2VjdG8xIDwtIGxlZnRfam9pbihyZXNfZW5kb19vcl9lY3RvMSwga19lbmRvX29yX2VjdG8sIGJ5ID0gIGMoIm5hbWUiID0gImVuZG9fb3JfZWN0byIpKSAgJT4lIGxlZnRfam9pbihwcmVkX2VuZG9fb3JfZWN0bykKI3Jlc19zeW1iaW9zaXMxIAojIGRyYXdpbmcgYSBmdW5uZWwgcGxvdCAtIGZpZyAyYgpmaWdfZW5kb19vcl9lY3RvIDwtIGdncGxvdChkYXRhID0gcmVzX2VuZG9fb3JfZWN0bzEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShlbmRvX29yX2VjdG8pKSwgCiAgICAgICAgICAgICAgICAgICBhZXMoeD0gdGFuaChaciksIHkgPSBlbmRvX29yX2VjdG8sIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBlbmRvX29yX2VjdG8pLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJFbmRvL0VjdG8iID0gIiMwMDcyQjIiLCAgIkVuZG8iID0gIiNENTVFMDAiLCAgIkVjdG8iPSAiI0NDNzlBNyIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiRW5kby9FY3RvIiA9ICIjMDA3MkIyIiwgICJFbmRvIiA9ICIjRDU1RTAwIiwgICJFY3RvIj0gIiNDQzc5QTciKSkgKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiRW5kby9FY3RvIiA9ICJCb3RoIiwgICJFbmRvIiA9ICJFbmRvc3ltYmlvc2lzIiwgICJFY3RvIj0gIkVjdG9zeW1iaW9zaXMiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSAxOjMgKyAwLjE1LCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX2VuZG9fb3JfZWN0bzEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdGlvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpICsKICAjIGFkZGluZyBpbWFnZXMKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2VuZG9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2VjdG9wYXJhc2l0ZSksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjgsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9lY3RvcGFyYXNpdGUpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9lbmRvcGFyYXNpdGUpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSAwLjYsIHltYXggPSAxLjIpCgpmaWdfZW5kb19vcl9lY3RvCgojIGZpZyAzZQoKZSA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19lbmRvX29yX2VjdG8xLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoZW5kb19vcl9lY3RvKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gZW5kb19vcl9lY3RvLCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gZW5kb19vcl9lY3RvKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiRW5kby9FY3RvIiA9ICIjMDA3MkIyIiwgICJFbmRvIiA9ICIjRDU1RTAwIiwgICJFY3RvIj0gIiNDQzc5QTciKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIkVuZG8vRWN0byIgPSAiIzAwNzJCMiIsICAiRW5kbyIgPSAiI0Q1NUUwMCIsICAiRWN0byI9ICIjQ0M3OUE3IikpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIkVuZG8vRWN0byIgPSAiQm90aCIsICAiRW5kbyIgPSAiRW5kb3N5bWJpb3NpcyIsICAiRWN0byI9ICJFY3Rvc3ltYmlvc2lzIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAwLjkzLCB5ID0gMTozICsgMC4xNSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19lbmRvX29yX2VjdG8xJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSksIHRhZyA9ICJlIiApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgYWRkaW5nIGltYWdlcwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfZW5kb3BhcmFzaXRlKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDEuNiwgeW1heCA9IDIuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfZWN0b3BhcmFzaXRlKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuOCwgeW1pbiA9IDIuNiwgeW1heCA9IDMuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2VjdG9wYXJhc2l0ZSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2VuZG9wYXJhc2l0ZSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikKYGBgCgoqKkZpZ3VyZSA0YToqKiAgQW4gb3JjaGFyZCBwbG90IHNob3dpbmcgdGhlIGdyb3VwLXdpc2UgbWVhbnMgKHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBgZW5kb19vcl9lY3RvYCkgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKHRoaWNrIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzICh0aGluIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuIAoKCiMjIyMgVGhlIGVmZmVjdCBvZiB0aGUgbW9kZSBvZiB0cmFuc21pc3Npb24KCmBgYHtyfQojIG1ldGEtcmVncmVzc2lvbjogbXV0aXBsZSBpbnRlcmNlcHRzCm1yX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMQptcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojIG1ldGEtcmVncmVzc2lvbjogY29udHJhc3QgMgptcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQsIHJlZiA9ICJ2ZXJ0aWNhbCIpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCmBgYAoKIyMjIyBUYWJsZSBTMy43ClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChlc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkYC4gIE5vdGUgdGhhdCBgbXVgIG1lYW5zIHRoZSBncm91cCBtZWFuIHdoaWxlIGBiZXRhYCByZXByZXNlbnRzIHRoZSBjb250cmFzdCBiZXR3ZWVuIHR3byBncm91cHMgaW4gdGhlIFVuaXQgY29sdW1uLgpgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBSMihtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCnJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMgPC0gZ2V0X2VzdChtcl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMsIG1vZCA9ICJtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSxhcy5jaGFyYWN0ZXIocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRuYW1lKSxjb250X2dlbihyZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJG5hbWUpKSwKICAgYFVuaXRgID0gYyhyZXAoYygiWnIgKG11KSIsICJyIChtdSkiKSxlYWNoID0gMyksIHJlcCgiWnIgKGJldGEpIiwgMykpLAogIEVzdGltYXRlID0gYyhyZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJGVzdGltYXRlLCB0YW5oKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkZXN0aW1hdGUpLCByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQyJGVzdGltYXRlWy0xXSwgIHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMkZXN0aW1hdGVbLSgxOjIpXSksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJGxvd2VyQ0wsIHRhbmgocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRsb3dlckNMKSwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMiRsb3dlckNMWy0xXSwgcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMyRsb3dlckNMWy0oMToyKV0pLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkdXBwZXJDTCx0YW5oKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkdXBwZXJDTCksIHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIkdXBwZXJDTFstMV0sIHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMkdXBwZXJDTFstKDE6MildKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSRzaWdtYTIsICByZXAoTkEsIDgpKSwKICBgUjJgID0gYyhyMl9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDFbMV0sIHJlcChOQSwgOCkpKSAtPiB0X3RyYW5zbWlzc2lvbgoKdF90cmFuc21pc3Npb24gJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgojIyMjIEZpZ3VyZSA0YgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDMuNX0KIyBnZXR0aW5nIGltYWdlcwppbWFnZV9ob3Jpem9udGFsIDwtIHJlYWRQTkcoaGVyZSgiaW1hZ2VzL2hvcml6b250YWxfdHJhbnNwYXJlbnRiZy5wbmciKSkKaW1hZ2VfdmVydGljYWwgPC0gcmVhZFBORyhoZXJlKCJpbWFnZXMvdmVydGljYWxfdHJhbnNwYXJlbnRiZy5wbmciKSkKaW1hZ2VfYm90aCA8LSByZWFkUE5HKGhlcmUoImltYWdlcy9ob3Jpem9udGFsX3ZlcnRpY2FsX3RyYW5zcGFyZW50YmcucG5nIikpCiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIDwtIGRhdCAlPiUgZ3JvdXBfYnkobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpICU+JSBjb3VudCgpCiMgZ2V0dGluZyBlc3RpbWF0ZXMgYW5kIHByZWRpY2l0b25zCnByZWRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gZ2V0X3ByZWQobXJfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxLCBtb2QgPSAibW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQiKSAKcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSA8LSBsZWZ0X2pvaW4ocmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSwga19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgYnkgPSAgYygibmFtZSIgPSAibW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCkKI3Jlc19zeW1iaW9zaXMxIAojIGRyYXdpbmcgYSBmdW5uZWwgcGxvdCAtIGZpZyAyYgpmaWdfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gZ2dwbG90KGRhdGEgPSByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpKSwgCiAgICAgICAgICAgICAgICAgICBhZXMoeD0gdGFuaChaciksIHkgPSBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgc2l6ZSA9ICgoMS9WWnIpICsgMyksIGNvbG91ciA9IG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYm90aCIgPSAiIzAwNzJCMiIsICAiaG9yaXpvbnRhbCIgPSAiI0Q1NUUwMCIsICAidmVydGljYWwiPSAiI0NDNzlBNyIpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYm90aCIgPSAiIzAwNzJCMiIsICAiaG9yaXpvbnRhbCIgPSAiI0Q1NUUwMCIsICAidmVydGljYWwiPSAiI0NDNzlBNyIpKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJib3RoIiA9ICJCb3RoIiwgICJob3Jpem9udGFsIiA9ICJIb3Jpem9udGFsIiwgICJ2ZXJ0aWNhbCI9ICJWZXJ0aWNhbCIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9ICgxOjMgKyAwLjE1KSwgbGFiZWw9IHBhc3RlKCJpdGFsaWMoayk9PSIsIHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdGlvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpICsKICAjIGFkZGluZyBpbWFnZXMKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2hvcml6b250YWwpLCB4bWluID0gLTEsIHhtYXggPSAtMC43LCB5bWluID0gMS40LCB5bWF4ID0gMi4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0aWNhbCksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjcsIHltaW4gPSAyLjQsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9ib3RoKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuNywgeW1pbiA9IDAuNCwgeW1heCA9IDEuMikgCgpmaWdfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQKCiMgZmlnIDNmCgpmIDwtIGdncGxvdChkYXRhID0gcmVzX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSwgYWVzKHggPSB0YW5oKGVzdGltYXRlKSwgeSA9IG5hbWUpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cz1jKC0xLCAxKSwgYnJlYWtzID0gc2VxKC0xLCAxLCBieSA9IDAuMikgKSArCiAgZ2VvbV9xdWFzaXJhbmRvbShkYXRhID0gZGF0ICU+JSBmaWx0ZXIoIWlzLm5hKG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkKSksIAogICAgICAgICAgICAgICAgICAgYWVzKHg9IHRhbmgoWnIpLCB5ID0gbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCksIGdyb3VwT25YID0gRkFMU0UsIGFscGhhPTAuNCkgKyAKICAjIDk1ICVwcmVjaXRpb24gaW50ZXJ2YWwgKFBJKQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlclBSKSwgeG1heCA9IHRhbmgodXBwZXJQUikpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMC41LCBhbHBoYSA9IDAuNikgKwogICMgOTUgJUNJCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyQ0wpLCB4bWF4ID0gdGFuaCh1cHBlckNMKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAxLjIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9IDIsIGNvbG91ciA9ICJibGFjayIsIGFscGhhID0gMC4zKSArCiAgIyBjcmVhdGluZyBkb3RzIGFuZCBkaWZmZXJlbnQgc2l6ZSAoYmVlLXN3YXJtIGFuZCBidWJibGVzKQogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBuYW1lKSwgc2l6ZSA9IDMsIHNoYXBlID0gMjEpICsgIwogICMgc2V0dGluZyBjb2xvdXJzCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImJvdGgiID0gIiMwMDcyQjIiLCAgImhvcml6b250YWwiID0gIiNENTVFMDAiLCAgInZlcnRpY2FsIj0gIiNDQzc5QTciKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImJvdGgiID0gIiMwMDcyQjIiLCAgImhvcml6b250YWwiID0gIiNENTVFMDAiLCAgInZlcnRpY2FsIj0gIiNDQzc5QTciKSkgKwogIHNjYWxlX3lfZGlzY3JldGUobGFiZWxzID0gYygiYm90aCIgPSAiQm90aCIsICAiaG9yaXpvbnRhbCIgPSAiSG9yaXpvbnRhbCIsICAidmVydGljYWwiPSAiVmVydGljYWwiKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSAoMTozICsgMC4xNSksIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSAiIiwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSksIHRhZyA9ICJmIiApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICMgYWRkaW5nIGltYWdlcwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaG9yaXpvbnRhbCksIHhtaW4gPSAtMSwgeG1heCA9IC0wLjcsIHltaW4gPSAxLjQsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3ZlcnRpY2FsKSwgeG1pbiA9IC0xLCB4bWF4ID0gLTAuNywgeW1pbiA9IDIuNCwgeW1heCA9IDMuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2JvdGgpLCB4bWluID0gLTEsIHhtYXggPSAtMC43LCB5bWluID0gMC40LCB5bWF4ID0gMS4yKSAKCgpgYGAKCioqRmlndXJlIDRiOioqIEFuIG9yY2hhcmQgcGxvdCBzaG93aW5nIHRoZSBncm91cC13aXNlIG1lYW5zICh0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgYG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkYCksIGluZGljYXRpbmcgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzICh0aGljayBsaW5lcykgYW5kIDk1JSBwcmVkaWN0aW9uIGludGVydmFscyAodGhpbiBsaW5lcyksIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLgoKCiMjIyMgVGhlIGNvbWJpbmVkIGVmZmVjdCBvZiBzeW1iaW9zaXMgYW5kIG1vZGUgb2YgdHJhbnNtaXNzaW9uCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9zaXNfdHJhbnNtaXNzaW9uIDwtIGZhY3RvcihkYXQkc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTXV0dWFsaXN0Ym90aCIsICJNdXR1YWxpc3Rob3Jpem9udGFsIiwiTXV0dWFsaXN0dmVydGljYWwiLCAiUGFyYXNpdGVib3RoIiwgIlBhcmFzaXRlaG9yaXpvbnRhbCIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk11dHVhbGlzdEJvdGgiLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCIsIk11dHVhbGlzdFZlcnRpY2FsIiwgIlBhcmFzaXRlQm90aCIsICJQYXJhc2l0ZUhvcml6b250YWwiKSkKCiMgbWV0YS1yZWdyZXNzaW9uOiBtdXRpcGxlIGludGVyY2VwdHMKbXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3Npc190cmFuc21pc3Npb24gLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojICMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdHMgeCAxMAojIGdldHRpbmcgdGhlIGxldmVsIG5hbWVzIG91dApsZXZlbF9uYW1lcyA8LSBsZXZlbHMoZGF0JHN5bWJpb3Npc190cmFuc21pc3Npb24pCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvc2lzX3RyYW5zbWlzc2lvbiwgcmVmID0gbmFtZSksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKfQoKIyByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbiBpbmNsdWRpbmcgYWxsIGNvbnRyYXN0IHJlc3VsdHM7IHRha2luZyB0aGUgbGFzdCBsZXZlbCBvdXQgKFstbGVuZ3RoKGxldmVsX25hbWVzKV0pCm1yX3N5bWJpb3Npc190cmFuc21pc3Npb24gPC0gbWFwKGxldmVsX25hbWVzWy1sZW5ndGgobGV2ZWxfbmFtZXMpXSwgcnVuX3JtYSkKCmBgYAoKIyMjIyBUYWJsZSBTMy44ClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChlc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHN5bWJpb3Npc190cmFuc21pc3Npb25gLiAgTm90ZSB0aGF0IGBtdWAgbWVhbnMgdGhlIGdyb3VwIG1lYW4gd2hpbGUgYGJldGFgIHJlcHJlc2VudHMgdGhlIGNvbnRyYXN0IGJldHdlZW4gdHdvIGdyb3VwcyBpbiB0aGUgVW5pdCBjb2x1bW4uCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEgPC0gUjIobXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSA8LSBnZXRfZXN0KG1yX3N5bWJpb3Npc190cmFuc21pc3Npb24xLCBtb2QgPSAic3ltYmlvc2lzX3RyYW5zbWlzc2lvbiIpCnJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uIDwtIG1hcChtcl9zeW1iaW9zaXNfdHJhbnNtaXNzaW9uLCB+IGdldF9lc3QoLngsIG1vZCA9ICJzeW1iaW9zaXNfdHJhbnNtaXNzaW9uIikpCgojIGEgbGlzdCBvZiB0aGUgbnVtYmVycyB0byB0YWtlIG91dCB1bm5lY2Vzc2FyeSBjb250cmFzdHMKY29udHJhX2xpc3QgPC0gTWFwKHNlcSwgZnJvbT0xLCB0bz0xOjQpCgojIHlvdSBuZWVkIHRvIGZsYXR0ZW4gdHdpY2U6IGZpcnN0IHRvIG1ha2UgaXQgYSBsaXN0IGFuZCBtYWtlIGl0IGEgdmVjdG9yCmVzdGltYXRlcyA8LSBtYXAyKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJlc3RpbWF0ZSJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCmxvd2VyQ0xzIDwtIG1hcDIocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24sIGNvbnRyYV9saXN0LCB+LnhbLSgueSksImxvd2VyQ0wiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQp1cHBlckNMcyA8LSBtYXAyKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJ1cHBlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkbmFtZSksYXMuY2hhcmFjdGVyKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSRuYW1lKSwgY29udF9nZW4ocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJG5hbWUpKSwKICBgVW5pdGAgPSBjKHJlcChjKCJaciAobXUpIiwgInIgKG11KSIpLGVhY2ggPSA1KSwgcmVwKCJaciAoYmV0YSkiLCAxMCkpLAogIEVzdGltYXRlID0gYyhyZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkZXN0aW1hdGUsIHRhbmgocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJGVzdGltYXRlKSwgZXN0aW1hdGVzKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSRsb3dlckNMLCB0YW5oKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSRsb3dlckNMKSwgbG93ZXJDTHMpLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSR1cHBlckNMLHRhbmgocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xJHVwcGVyQ0wpLCB1cHBlckNMcyksCiAgYFZbYXV0aG9yc11gID0gYyhtcl9zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSRzaWdtYTIsICByZXAoTkEsICg1ICsgNSArIGNob29zZSg1LDIpKS0gMSkpLAogIGBSMmAgPSBjKHIyX3N5bWJpb3Npc190cmFuc21pc3Npb24xWzFdLCByZXAoTkEsICg1KzUgKyBjaG9vc2UoNSwgMikpLSAxKSkpICU+JSBrYWJsZSgiaHRtbCIsICBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpCmBgYAojIyMjIEZpZ3VyZSA0YwpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDV9CiMgY29sb3VyIGxpc3QKY29sb3VyX2xzIDwtIGMoIiMwMDAwMDAiLCAiI0U2OUYwMCIsICIjNTZCNEU5IiwgIiMwMDlFNzMiLCAgIiNGMEU0MjIiLCAgIiMwMDcyQjIiLCAgIiNENTVFMDAiLCAiI0NDNzlBNyIsICIjMDAwMDhCIiwgIiM4QjBBNTAiLCAiIzU0RkY5RiIsICIjOTk5OTk5IikKCiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX3N5bWJpb3Npc190cmFuc21pc3Npb24gPC0gZGF0ICU+JSBncm91cF9ieShzeW1iaW9zaXNfdHJhbnNtaXNzaW9uKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX3N5bWJpb3Npc190cmFuc21pc3Npb24gPC0gZ2V0X3ByZWQobXJfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEsIG1vZCA9ICJzeW1iaW9zaXNfdHJhbnNtaXNzaW9uIikgCnJlc19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uMSA8LSBsZWZ0X2pvaW4ocmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xLCBrX3N5bWJpb3Npc190cmFuc21pc3Npb24sIGJ5ID0gIGMoIm5hbWUiID0gInN5bWJpb3Npc190cmFuc21pc3Npb24iKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9zeW1iaW9zaXNfdHJhbnNtaXNzaW9uKQojcmVzX3N5bWJpb3NpczEgCiMgZHJhd2luZyBhIGZ1bm5lbCBwbG90IC0gZmlnIDJiCmZpZ19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uIDwtIGdncGxvdChkYXRhID0gcmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvc2lzX3RyYW5zbWlzc2lvbikpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IHN5bWJpb3Npc190cmFuc21pc3Npb24sIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBzeW1iaW9zaXNfdHJhbnNtaXNzaW9uKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICBjKCJNdXR1YWxpc3RCb3RoIj0gY29sb3VyX2xzWzFdLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCI9IGNvbG91cl9sc1syXSwgIk11dHVhbGlzdFZlcnRpY2FsIiA9IGNvbG91cl9sc1szXSwiUGFyYXNpdGVCb3RoIj0gY29sb3VyX2xzWzRdLCAiUGFyYXNpdGVIb3Jpem9udGFsIiA9IGNvbG91cl9sc1s1XSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNdXR1YWxpc3RCb3RoIj0gY29sb3VyX2xzWzFdLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCI9IGNvbG91cl9sc1syXSwgIk11dHVhbGlzdFZlcnRpY2FsIiA9IGNvbG91cl9sc1szXSwiUGFyYXNpdGVCb3RoIj0gY29sb3VyX2xzWzRdLCAiUGFyYXNpdGVIb3Jpem9udGFsIiA9IGNvbG91cl9sc1s1XSkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk11dHVhbGlzdEJvdGgiID0gIk11dHVhbGlzdC1cbkJvdGgiLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCIgPSAiTXV0dWFsaXN0LVxuSG9yaXpvbnRhbCIsIk11dHVhbGlzdFZlcnRpY2FsIiA9ICJNdXR1YWxpc3QtXG5WZXJ0aWNhbCIsICJQYXJhc2l0ZUJvdGgiID0gIlBhcmFzaXRlLVxuQm90aCIsICJQYXJhc2l0ZUhvcml6b250YWwiID0gIlBhcmFzaXRlLVxuSG9yaXpvbnRhbCIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9IDE6NSArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdGlvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpICkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSArCiAgIyBwdXR0aW5nIHBpY3R1cmVzIGluCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9ib3RoKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC42LCB5bWluID0gMC40LCB5bWF4ID0gMS4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9ob3Jpem9udGFsKSx4bWluID0gLTAuOSwgeG1heCA9IC0wLjYsIHltaW4gPSAxLjQsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX211dHVhbGlzbSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDIuNiwgeW1heCA9IDMuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3ZlcnRpY2FsKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC42LCB5bWluID0gMi40LCB5bWF4ID0gMy4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfYm90aCksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNiwgeW1pbiA9IDMuNCwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDQuNiwgeW1heCA9IDUuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaG9yaXpvbnRhbCksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNiwgeW1pbiA9IDQuNCwgeW1heCA9IDUuMikKCmZpZ19zeW1iaW9zaXNfdHJhbnNtaXNzaW9uCgojIyBmaWcgMwpnIDwtIGdncGxvdChkYXRhID0gcmVzX3N5bWJpb3Npc190cmFuc21pc3Npb24xLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvc2lzX3RyYW5zbWlzc2lvbikpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IHN5bWJpb3Npc190cmFuc21pc3Npb24sIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBzeW1iaW9zaXNfdHJhbnNtaXNzaW9uKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gICBjKCJNdXR1YWxpc3RCb3RoIj0gY29sb3VyX2xzWzFdLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCI9IGNvbG91cl9sc1syXSwgIk11dHVhbGlzdFZlcnRpY2FsIiA9IGNvbG91cl9sc1szXSwiUGFyYXNpdGVCb3RoIj0gY29sb3VyX2xzWzRdLCAiUGFyYXNpdGVIb3Jpem9udGFsIiA9IGNvbG91cl9sc1s1XSkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNdXR1YWxpc3RCb3RoIj0gY29sb3VyX2xzWzFdLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCI9IGNvbG91cl9sc1syXSwgIk11dHVhbGlzdFZlcnRpY2FsIiA9IGNvbG91cl9sc1szXSwiUGFyYXNpdGVCb3RoIj0gY29sb3VyX2xzWzRdLCAiUGFyYXNpdGVIb3Jpem9udGFsIiA9IGNvbG91cl9sc1s1XSkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk11dHVhbGlzdEJvdGgiID0gIk11dHVhbGlzdC1cbkJvdGgiLCAiTXV0dWFsaXN0SG9yaXpvbnRhbCIgPSAiTXV0dWFsaXN0LVxuSG9yaXpvbnRhbCIsIk11dHVhbGlzdFZlcnRpY2FsIiA9ICJNdXR1YWxpc3QtXG5WZXJ0aWNhbCIsICJQYXJhc2l0ZUJvdGgiID0gIlBhcmFzaXRlLVxuQm90aCIsICJQYXJhc2l0ZUhvcml6b250YWwiID0gIlBhcmFzaXRlLVxuSG9yaXpvbnRhbCIpKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9IDE6NSArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfc3ltYmlvc2lzX3RyYW5zbWlzc2lvbjEkbiksIHBhcnNlPVRSVUUsIGhqdXN0ID0gImxlZnQiLCBzaXplPTMuNSkgKwogIGxhYnMoeCA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKHIpLCAiIChjb3JyZWxhdGlvbikiKSksIHkgPSAiIiwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpICx0YWcgPSAiZyIgKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIixoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpICsKICAjIHB1dHRpbmcgcGljdHVyZXMgaW4KICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX211dHVhbGlzbSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2JvdGgpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjYsIHltaW4gPSAwLjQsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2hvcml6b250YWwpLHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNiwgeW1pbiA9IDEuNCwgeW1heCA9IDIuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMi42LCB5bWF4ID0gMy4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfdmVydGljYWwpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjYsIHltaW4gPSAyLjQsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wYXJhc2l0aXNtKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMy42LCB5bWF4ID0gNC4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9ib3RoKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC42LCB5bWluID0gMy40LCB5bWF4ID0gNC4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wYXJhc2l0aXNtKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gNC42LCB5bWF4ID0gNS4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9ob3Jpem9udGFsKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC42LCB5bWluID0gNC40LCB5bWF4ID0gNS4yKQoKYGBgCgoqKkZpZ3VyZSA0YzoqKiBBbiBvcmNoYXJkIHBsb3Qgc2hvd2luZyB0aGUgZ3JvdXAtd2lzZSBtZWFucyAodGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGBzeW1iaW9zaXNfdHJhbnNtaXNzaW9uYCkgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKHRoaWNrIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzICh0aGluIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuCgojIyMjIFB1dHRpbmcgdG9nZXRoZXIgRmlndXJlIDMKCmBgYHtyLCBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD0gMTR9CiMgYnVpbGRpbmcgZmlnIDMgdXNpbmcgcGF0Y2h3b3JrCmZpZzMgPC0gKGEgLyBiIC8gYyAvIGQgKyBwbG90X2xheW91dChoZWlnaHRzID0gYygxLjYsIDIsIDMuNywgMy43KSkpCgoKI2ZpZzMgPC0gKGEgLyBiIC8gYyAvIGQgKyBwbG90X2xheW91dChoZWlnaHRzID0gYygxLjYsIDIsIDMuNywgMy43KSkpIHwgCiAjIChlIC8gZiAvIGcgKyBwbG90X2xheW91dChoZWlnaHRzID0gYygyLjgsIDIuOCwgNC40KSkpICMrIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gJ2EnLCB0YWdfc3VmZml4ID0gJyknKQogCmZpZzMKCiMgZ2dzYXZlKGhlcmUoImZpZ3MvZmlnMy5wbmciKSwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMikKIyBnZ3NhdmUoaGVyZSgiZmlncy9maWczLnBkZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyKQpgYGAKKipGaWd1cmUgMzoqKiBwdXR0aW5nIGFsbCA0IHBhbmVscyB0b2dldGhlcjogRmlndXJlIDNhIC0gRmlndXJlIDNkIChzZWUgdGhlIG1haW4gdGV4dCkKCiMjIyMgUHV0dGluZyB0b2dldGhlciBGaWd1cmUgNAoKYGBge3IsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PSAxNH0KIyBidWlsZGluZyBmaWcgMyB1c2luZyBwYXRjaHdvcmsKZmlnNCA8LSAoZSAvIGYgLyBnICsgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMi44LCAyLjgsIDQuNCkpKSArIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gJ2EnKQogCmZpZzQKCiMgZ2dzYXZlKGhlcmUoImZpZ3MvZmlnNC5wbmciKSwgd2lkdGggPSA4LCBoZWlnaHQgPSAxMikKIyBnZ3NhdmUoaGVyZSgiZmlncy9maWc0LnBkZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDEyKQpgYGAKCioqRmlndXJlIDQ6KiogcHV0dGluZyBhbGwgMyBwYW5lbHMgdG9nZXRoZXI6IEZpZ3VyZSA0YSAtIEZpZ3VyZSA0YyAoc2VlIHRoZSBtYWluIHRleHQpCgojIyMgQWRkaXRpb25hbCBhbmFseXNlcyAodW5pLXByZWRpY3RvcikKClRoZXNlIGFyZSBleHRyYSBhbmFseXNlcyBub3QgZGlzY3Vzc2VkIGluIHRoZSBtYWluIHRleHQuIAoKIyMjIyBUaGUgY29tYmluZWQgZWZmZWN0IG9mIGhvc3QgdGF4YSBhbmQgc3ltYmlvc2lzIChwYXJhc2l0aXNtIHZzLiBtdXR1YWxpc20pCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRob3N0X3RheF9zeW1iaW9zaXMgPC0gZmFjdG9yKGRhdCRob3N0X3RheF9zeW1iaW9zaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJNaWNyb2JlTXV0dWFsaXN0IiwgIk1pY3JvYmVQYXJhc2l0ZSIsICAiUGxhbnRNdXR1YWxpc3QiLCAiUGxhbnRQYXJhc2l0ZSIsICJJbnZlcnRNdXR1YWxpc3QiLCAgIkludmVydFBhcmFzaXRlIiwgICJWZXJ0TXV0dWFsaXN0IiwgIlZlcnRQYXJhc2l0ZSIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11dGlwbGUgaW50ZXJjZXB0cwptcl9ob3N0X3RheF9zeW1iaW9zaXMxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBob3N0X3RheF9zeW1iaW9zaXMgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojICMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdHMgeCAxMAojIGdldHRpbmcgdGhlIGxldmVsIG5hbWVzIG91dApsZXZlbF9uYW1lcyA8LSBsZXZlbHMoZGF0JGhvc3RfdGF4X3N5bWJpb3NpcykKCiMgaGVscGVyIGZ1bmN0aW9uIHRvIHJ1biBtZXRhZm9yIG1ldGEtcmVncmVzc2lvbgpydW5fcm1hIDwtIGZ1bmN0aW9uKG5hbWUpIHsKICBybWEubXYoeWkgPSBaciwgCiAgICAgICAgICAgICAgICAgICAgICAgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gcmVsZXZlbChob3N0X3RheF9zeW1iaW9zaXMsIHJlZiA9IG5hbWUpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCn0KCiMgcmVzdWx0cyBvZiBtZXRhLXJlZ3Jlc3Npb24gaW5jbHVkaW5nIGFsbCBjb250cmFzdCByZXN1bHRzOyB0YWtpbmcgdGhlIGxhc3QgbGV2ZWwgb3V0IChbLWxlbmd0aChsZXZlbF9uYW1lcyldKQptcl9ob3N0X3RheF9zeW1iaW9zaXMgPC0gbWFwKGxldmVsX25hbWVzWy1sZW5ndGgobGV2ZWxfbmFtZXMpXSwgcnVuX3JtYSkKCmBgYAoKIyMjIyBUYWJsZSBTMy45ClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYGhvc3RfdGF4X3N5bWJpb3Npc2AuICBOb3RlIHRoYXQgYG11YCBtZWFucyB0aGUgZ3JvdXAgbWVhbiB3aGlsZSBgYmV0YWAgcmVwcmVzZW50cyB0aGUgY29udHJhc3QgYmV0d2VlbiB0d28gZ3JvdXBzIGluIHRoZSBVbml0IGNvbHVtbi4KYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9ob3N0X3RheF9zeW1iaW9zaXMxIDwtIFIyKG1yX2hvc3RfdGF4X3N5bWJpb3NpczEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19ob3N0X3RheF9zeW1iaW9zaXMxIDwtIGdldF9lc3QobXJfaG9zdF90YXhfc3ltYmlvc2lzMSwgbW9kID0gImhvc3RfdGF4X3N5bWJpb3NpcyIpCnJlc19ob3N0X3RheF9zeW1iaW9zaXMgPC0gbWFwKG1yX2hvc3RfdGF4X3N5bWJpb3NpcywgfiBnZXRfZXN0KC54LCBtb2QgPSAiaG9zdF90YXhfc3ltYmlvc2lzIikpCgojIGEgbGlzdCBvZiB0aGUgbnVtYmVycyB0byB0YWtlIG91dCB1bm5lY2Vzc2FyeSBjb250cmFzdHMKY29udHJhX2xpc3QgPC0gTWFwKHNlcSwgZnJvbT0xLCB0bz0xOjcpCgojIHlvdSBuZWVkIHRvIGZsYXR0ZW4gdHdpY2U6IGZpcnN0IHRvIG1ha2UgaXQgYSBsaXN0IGFuZCBtYWtlIGl0IGEgdmVjdG9yCmVzdGltYXRlcyA8LSBtYXAyKHJlc19ob3N0X3RheF9zeW1iaW9zaXMsIGNvbnRyYV9saXN0LCB+LnhbLSgueSksImVzdGltYXRlIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKbG93ZXJDTHMgPC0gbWFwMihyZXNfaG9zdF90YXhfc3ltYmlvc2lzLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJsb3dlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKdXBwZXJDTHMgPC0gbWFwMihyZXNfaG9zdF90YXhfc3ltYmlvc2lzLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJ1cHBlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKGFzLmNoYXJhY3RlcihyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSRuYW1lKSwgY29udF9nZW4ocmVzX2hvc3RfdGF4X3N5bWJpb3NpczEkbmFtZSkpLAogIEVzdGltYXRlID0gYyhyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSRlc3RpbWF0ZSwgZXN0aW1hdGVzKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19ob3N0X3RheF9zeW1iaW9zaXMxJGxvd2VyQ0wsbG93ZXJDTHMpLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSBjKHJlc19ob3N0X3RheF9zeW1iaW9zaXMxJHVwcGVyQ0wsdXBwZXJDTHMpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfaG9zdF90YXhfc3ltYmlvc2lzMSRzaWdtYTIsICByZXAoTkEsICg4ICsgY2hvb3NlKDgsMikpLSAxKSksCiAgYFIyYCA9IGMocjJfaG9zdF90YXhfc3ltYmlvc2lzMVsxXSwgcmVwKE5BLCAoOCArIGNob29zZSg4LCAyKSktIDEpKSkgJT4lIGthYmxlKCJodG1sIiwgIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgJT4lCiAgc2Nyb2xsX2JveCh3aWR0aCA9ICIxMDAlIiwgaGVpZ2h0ID0gIjMwMHB4IikKYGBgCiMjIyMgRmlndXJlIFMzLjMKCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gOH0KIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5CmtfaG9zdF90YXhfc3ltYmlvc2lzIDwtIGRhdCAlPiUgZ3JvdXBfYnkoaG9zdF90YXhfc3ltYmlvc2lzKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX2hvc3RfdGF4X3N5bWJpb3NpcyA8LSBnZXRfcHJlZChtcl9ob3N0X3RheF9zeW1iaW9zaXMxLCBtb2QgPSAiaG9zdF90YXhfc3ltYmlvc2lzIikgCnJlc19ob3N0X3RheF9zeW1iaW9zaXMxIDwtIGxlZnRfam9pbihyZXNfaG9zdF90YXhfc3ltYmlvc2lzMSwga19ob3N0X3RheF9zeW1iaW9zaXMsIGJ5ID0gIGMoIm5hbWUiID0gImhvc3RfdGF4X3N5bWJpb3NpcyIpKSAgJT4lIGxlZnRfam9pbihwcmVkX2hvc3RfdGF4X3N5bWJpb3NpcykKI3Jlc19zeW1iaW9zaXMxIAojIGRyYXdpbmcgYSBmdW5uZWwgcGxvdCAtIGZpZyAyYgpmaWdfaG9zdF90YXhfc3ltYmlvc2lzIDwtIGdncGxvdChkYXRhID0gcmVzX2hvc3RfdGF4X3N5bWJpb3NpczEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShob3N0X3RheF9zeW1iaW9zaXMpKSwgCiAgICAgICAgICAgICAgICAgICBhZXMoeD0gdGFuaChaciksIHkgPSBob3N0X3RheF9zeW1iaW9zaXMsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBob3N0X3RheF9zeW1iaW9zaXMpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgIGMoIk1pY3JvYmVNdXR1YWxpc3QiPSBjb2xvdXJfbHNbMV0sICJNaWNyb2JlUGFyYXNpdGUiPSBjb2xvdXJfbHNbMl0sICAiUGxhbnRNdXR1YWxpc3QiPSBjb2xvdXJfbHNbM10sICJQbGFudFBhcmFzaXRlIj0gY29sb3VyX2xzWzRdLCAiSW52ZXJ0TXV0dWFsaXN0IiA9IGNvbG91cl9sc1s1XSwgICJJbnZlcnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s2XSwgIlZlcnRNdXR1YWxpc3QiPSBjb2xvdXJfbHNbN10sICAgICAiVmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzhdICkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJNaWNyb2JlTXV0dWFsaXN0Ij0gY29sb3VyX2xzWzFdLCAiTWljcm9iZVBhcmFzaXRlIj0gY29sb3VyX2xzWzJdLCAgIlBsYW50TXV0dWFsaXN0Ij0gY29sb3VyX2xzWzNdLCAiUGxhbnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s0XSwgIkludmVydE11dHVhbGlzdCIgPSBjb2xvdXJfbHNbNV0sICAiSW52ZXJ0UGFyYXNpdGUiPSBjb2xvdXJfbHNbNl0sICJWZXJ0TXV0dWFsaXN0Ij0gY29sb3VyX2xzWzddLCAgICAgIlZlcnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s4XSApKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJNaWNyb2JlTXV0dWFsaXN0Ij0gIk1pY3JvYmUtXG5NdXR1YWxpc3QiLCAiTWljcm9iZVBhcmFzaXRlIj0gIk1pY3JvYmUtXG5QYXJhc2l0ZSIsICAiUGxhbnRNdXR1YWxpc3QiID0gIlBsYW50LVxuTXV0dWFsaXN0IiwgIlBsYW50UGFyYXNpdGUiPSJQbGFudC1cblBhcmFzaXRlIiwgIkludmVydE11dHVhbGlzdCIgPSAiSW52ZXJ0ZWJyYXRlLVxuTXV0dWFsaXN0IiwgICAiSW52ZXJ0UGFyYXNpdGUiPSAiSW52ZXJ0ZWJyYXRlLVxuUGFyYXNpdGUiLCAiVmVydE11dHVhbGlzdCI9ICJWZXJ0ZWJyYXRlLVxuTXV0dWFsaXN0IiwgICJWZXJ0UGFyYXNpdGUiPSAiVmVydGVicmF0ZS1cblBhcmFzaXRlIiApKSArCiAgYW5ub3RhdGUoJ3RleHQnLCB4ID0gMC45MywgeSA9IDE6OCArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF90YXhfc3ltYmlvc2lzMSRuKSwgcGFyc2U9VFJVRSwgaGp1c3QgPSAibGVmdCIsIHNpemU9My41KSArCiAgbGFicyh4ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMociksICIgKGNvcnJlbGF0aW9uKSIpKSwgeSA9ICIiLCBzaXplID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMobiksICIgKCMgb2Ygc3BlY2llcyBwYWlycykiKSkgKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpICsKICAjIHB1dHRpbmcgcGljdHVyZXMgaW4KICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX21pY3JvYmVfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX211dHVhbGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX21pY3JvYmVfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDEuNiwgeW1heCA9IDIuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSkseG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gMS42LCB5bWF4ID0gMi4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wbGFudF9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMi42LCB5bWF4ID0gMy4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbXV0dWFsaXNtKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gMi42LCB5bWF4ID0gMy4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGxhbnRfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSA0LjYsIHltYXggPSA1LjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX211dHVhbGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDQuNiwgeW1heCA9IDUuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSA1LjYsIHltYXggPSA2LjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wYXJhc2l0aXNtKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gNS42LCB5bWF4ID0gNi4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfdmVydGVicmF0ZV9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gNi42LCB5bWF4ID0gNy4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSA2LjYsIHltYXggPSA3LjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3ZlcnRlYnJhdGVfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDcuNiwgeW1heCA9IDguMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDcuNiwgeW1heCA9IDguMikKCmZpZ19ob3N0X3RheF9zeW1iaW9zaXMKYGBgCgoqKkZpZ3VyZSBTMy4zOioqIEFuIG9yY2hhcmQgcGxvdCBzaG93aW5nIGdyb3VwLXdpc2UgbWVhbnMgKHRoZSBjYXRlZ29yaWNhbCB2YXJpYWJsZSBgaG9zdF90YXhfc3ltYmlvc2lzYCkgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKHRoaWNrIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gaW50ZXJ2YWxzICh0aGluIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuCgpTcGxpdHRpbmcgaG9zdCB0YXhvbm9teSBieSBtb2RlIG9mIHN5bWJpb3NpcyByZXZlYWxlZCB0aGF0IHRoZSBvYnNlcnZlZCBoaWdoZXIgcGh5bG9nZW5ldGljIGNvbmdydWVuY2Ugb2YgaG9zdC1zeW1iaW9udCBjb3BoeWxvZ2VuaWVzIGludm9sdmluZyBhIG1pY3JvYmlhbCBob3N0IGlzIGRyaXZlbiBwcmltYXJpbHkgYnkgZ3JlYXRlciBjb25ncnVlbmNlIGJldHdlZW4gbWljcm9iaWFsIGhvc3RzIGFuZCBtdXR1YWxpc3Qgc3ltYmlvbnRzLiBDb25ncnVlbmNlIGlzIGFsc28gcmVsYXRpdmVseSBoaWdoIGZvciBpbnZlcnRlYnJhdGUgaG9zdHMgdGhhdCBoYXJib3VyIGEgbXV0dWFsaXN0aWMgc3ltYmlvbnQsIHdoaWxlIGNvbmdydWVuY2UgYXBwZWFycyB0byBiZSBsb3dlc3QgZm9yIHBsYW50IGhvc3RzIHRoYXQgaGFyYm91ciBhIHBhcmFzaXRpYyBzeW1iaW9udC4gCgojIyMjIFRoZSBjb21iaW5lZCBlZmZlY3Qgb2Ygc3ltYmlvbnQgdGF4YSBhbmQgc3ltYmlvc2lzIChwYXJhc2l0aXNtIHZzLiBtdXR1YWxpc20pCgpgYGB7cn0KIyByZW9yZGVyaW5nCmRhdCRzeW1iaW9udF90YXhfc3ltYmlvc2lzIDwtIGZhY3RvcihkYXQkc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCAgIk1pY3JvYmVNdXR1YWxpc3QiLCAiTWljcm9iZVBhcmFzaXRlIiwgICJQbGFudE11dHVhbGlzdCIsICJQbGFudFBhcmFzaXRlIiwiSW52ZXJ0TXV0dWFsaXN0IiwgIkludmVydFBhcmFzaXRlIiwgIlZlcnRQYXJhc2l0ZSIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11bHRpcGxlIGludGVyY2VwdHMKbXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEgPC0gcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb250X3RheF9zeW1iaW9zaXMgLSAxLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCgojICMgbWV0YS1yZWdyZXNzaW9uOiBjb250cmFzdHMgeCAxMAojIGdldHRpbmcgdGhlIGxldmVsIG5hbWVzIG91dApsZXZlbF9uYW1lcyA8LSBsZXZlbHMoZGF0JHN5bWJpb250X3RheF9zeW1iaW9zaXMpCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgcmVmID0gbmFtZSksIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKfQoKIyByZXN1bHRzIG9mIG1ldGEtcmVncmVzc2lvbiBpbmNsdWRpbmcgYWxsIGNvbnRyYXN0IHJlc3VsdHM7IHRha2luZyB0aGUgbGFzdCBsZXZlbCBvdXQgKFstbGVuZ3RoKGxldmVsX25hbWVzKV0pCm1yX3N5bWJpb250X3RheF9zeW1iaW9zaXMgPC0gbWFwKGxldmVsX25hbWVzWy1sZW5ndGgobGV2ZWxfbmFtZXMpXSwgcnVuX3JtYSkKCmBgYAoKIyMjIyBUYWJsZSBTMy4xMApSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9udF90YXhfc3ltYmlvc2lzYC4gIE5vdGUgdGhhdCBgbXVgIG1lYW5zIHRoZSBncm91cCBtZWFuIHdoaWxlIGBiZXRhYCByZXByZXNlbnRzIHRoZSBjb250cmFzdCBiZXR3ZWVuIHR3byBncm91cHMgaW4gdGhlIFVuaXQgY29sdW1uLgpgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3N5bWJpb250X3RheF9zeW1iaW9zaXMxIDwtIFIyKG1yX3N5bWJpb250X3RheF9zeW1iaW9zaXMxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEgPC0gZ2V0X2VzdChtcl9zeW1iaW9udF90YXhfc3ltYmlvc2lzMSwgbW9kID0gInN5bWJpb250X3RheF9zeW1iaW9zaXMiKQpyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcyA8LSBtYXAobXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgfiBnZXRfZXN0KC54LCBtb2QgPSAic3ltYmlvbnRfdGF4X3N5bWJpb3NpcyIpKQoKIyBhIGxpc3Qgb2YgdGhlIG51bWJlcnMgdG8gdGFrZSBvdXQgdW5uZWNlc3NhcnkgY29udHJhc3RzCmNvbnRyYV9saXN0IDwtIE1hcChzZXEsIGZyb209MSwgdG89MTo2KQoKIyB5b3UgbmVlZCB0byBmbGF0dGVuIHR3aWNlOiBmaXJzdCB0byBtYWtlIGl0IGEgbGlzdCBhbmQgbWFrZSBpdCBhIHZlY3Rvcgplc3RpbWF0ZXMgPC0gbWFwMihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwiZXN0aW1hdGUiXSkgJT4lIGZsYXR0ZW4oKSAlPiUgZmxhdHRlbl9kYmwoKQpsb3dlckNMcyA8LSBtYXAyKHJlc19zeW1iaW9udF90YXhfc3ltYmlvc2lzLCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJsb3dlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKdXBwZXJDTHMgPC0gbWFwMihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpcywgY29udHJhX2xpc3QsIH4ueFstKC55KSwidXBwZXJDTCJdKSAlPiUgZmxhdHRlbigpICU+JSBmbGF0dGVuX2RibCgpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYyhhcy5jaGFyYWN0ZXIocmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxJG5hbWUpLCBjb250X2dlbihyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkbmFtZSkpLAogIEVzdGltYXRlID0gYyhyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkZXN0aW1hdGUsIGVzdGltYXRlcyksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyhyZXNfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkbG93ZXJDTCxsb3dlckNMcyksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxJHVwcGVyQ0wsdXBwZXJDTHMpLAogIGBWW2F1dGhvcnNdYCA9IGMobXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEkc2lnbWEyLCAgcmVwKE5BLCAoNyArIGNob29zZSg3LDIpKS0gMSkpLAogIGBSMmAgPSBjKHIyX3N5bWJpb250X3RheF9zeW1iaW9zaXMxWzFdLCByZXAoTkEsICg3ICsgY2hvb3NlKDcsIDIpKS0gMSkpKSAlPiUga2FibGUoImh0bWwiLCAgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAlPiUKICBzY3JvbGxfYm94KHdpZHRoID0gIjEwMCUiLCBoZWlnaHQgPSAiMzAwcHgiKQpgYGAKIyMjIyBGaWd1cmUgUzMuNApgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDd9CiMgYWRkaW5nIHNhbXBsZSBzaXplIChrKSBmb3IgZWFjaCBjYXRlZ29yeQprX3N5bWJpb250X3RheF9zeW1iaW9zaXMgPC0gZGF0ICU+JSBncm91cF9ieShzeW1iaW9udF90YXhfc3ltYmlvc2lzKSAlPiUgY291bnQoKQojIGdldHRpbmcgZXN0aW1hdGVzIGFuZCBwcmVkaWNpdG9ucwpwcmVkX3N5bWJpb250X3RheF9zeW1iaW9zaXMgPC0gZ2V0X3ByZWQobXJfc3ltYmlvbnRfdGF4X3N5bWJpb3NpczEsIG1vZCA9ICJzeW1iaW9udF90YXhfc3ltYmlvc2lzIikgCnJlc19zeW1iaW9udF90YXhfc3ltYmlvc2lzMSA8LSBsZWZ0X2pvaW4ocmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxLCBrX3N5bWJpb250X3RheF9zeW1iaW9zaXMsIGJ5ID0gIGMoIm5hbWUiID0gInN5bWJpb250X3RheF9zeW1iaW9zaXMiKSkgICU+JSBsZWZ0X2pvaW4ocHJlZF9zeW1iaW9udF90YXhfc3ltYmlvc2lzKQojcmVzX3N5bWJpb3NpczEgCiMgZHJhd2luZyBhIGZ1bm5lbCBwbG90IC0gZmlnIDJiCmZpZ19zeW1iaW9udF90YXhfc3ltYmlvc2lzIDwtIGdncGxvdChkYXRhID0gcmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxLCBhZXMoeCA9IHRhbmgoZXN0aW1hdGUpLCB5ID0gbmFtZSkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoLTEsIDEpLCBicmVha3MgPSBzZXEoLTEsIDEsIGJ5ID0gMC4yKSApICsKICBnZW9tX3F1YXNpcmFuZG9tKGRhdGEgPSBkYXQgJT4lIGZpbHRlcighaXMubmEoc3ltYmlvbnRfdGF4X3N5bWJpb3NpcykpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IHN5bWJpb250X3RheF9zeW1iaW9zaXMsIHNpemUgPSAoKDEvVlpyKSArIDMpLCBjb2xvdXIgPSBzeW1iaW9udF90YXhfc3ltYmlvc2lzKSwgZ3JvdXBPblggPSBGQUxTRSwgYWxwaGE9MC40KSArIAogICMgOTUgJXByZWNpdGlvbiBpbnRlcnZhbCAoUEkpCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW4gPSB0YW5oKGxvd2VyUFIpLCB4bWF4ID0gdGFuaCh1cHBlclBSKSksICBoZWlnaHQgPSAwLCBzaG93LmxlZ2VuZCA9IEYsIHNpemUgPSAwLjUsIGFscGhhID0gMC42KSArCiAgIyA5NSAlQ0kKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJDTCksIHhtYXggPSB0YW5oKHVwcGVyQ0wpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDEuMikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gMiwgY29sb3VyID0gImJsYWNrIiwgYWxwaGEgPSAwLjMpICsKICAjIGNyZWF0aW5nIGRvdHMgYW5kIGRpZmZlcmVudCBzaXplIChiZWUtc3dhcm0gYW5kIGJ1YmJsZXMpCiAgZ2VvbV9wb2ludChhZXMoZmlsbCA9IG5hbWUpLCBzaXplID0gMywgc2hhcGUgPSAyMSkgKyAjCiAgIyBzZXR0aW5nIGNvbG91cnMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgIGMoIk1pY3JvYmVNdXR1YWxpc3QiPSBjb2xvdXJfbHNbMV0sICJNaWNyb2JlUGFyYXNpdGUiPSBjb2xvdXJfbHNbMl0sICAiUGxhbnRNdXR1YWxpc3QiPSBjb2xvdXJfbHNbM10sICJQbGFudFBhcmFzaXRlIj0gY29sb3VyX2xzWzRdLCAiSW52ZXJ0TXV0dWFsaXN0IiA9IGNvbG91cl9sc1s1XSwgICJJbnZlcnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s2XSwgIlZlcnRQYXJhc2l0ZSI9IGNvbG91cl9sc1s4XSApKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZU11dHVhbGlzdCI9IGNvbG91cl9sc1sxXSwgIk1pY3JvYmVQYXJhc2l0ZSI9IGNvbG91cl9sc1syXSwgICJQbGFudE11dHVhbGlzdCI9IGNvbG91cl9sc1szXSwgIlBsYW50UGFyYXNpdGUiPSBjb2xvdXJfbHNbNF0sICJJbnZlcnRNdXR1YWxpc3QiID0gY29sb3VyX2xzWzVdLCAgIkludmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzZdLCAiVmVydFBhcmFzaXRlIj0gY29sb3VyX2xzWzhdICkpICsKICBzY2FsZV95X2Rpc2NyZXRlKGxhYmVscyA9IGMoIk1pY3JvYmVNdXR1YWxpc3QiPSAiTWljcm9iZS1cbk11dHVhbGlzdCIsICJNaWNyb2JlUGFyYXNpdGUiPSAiTWljcm9iZS1cblBhcmFzaXRlIiwgICJQbGFudE11dHVhbGlzdCIgPSAiUGxhbnQtXG5NdXR1YWxpc3QiLCAiUGxhbnRQYXJhc2l0ZSI9IlBsYW50LVxuUGFyYXNpdGUiLCAiSW52ZXJ0TXV0dWFsaXN0IiA9ICJJbnZlcnRlYnJhdGUtXG5NdXR1YWxpc3QiLCAgICJJbnZlcnRQYXJhc2l0ZSI9ICJJbnZlcnRlYnJhdGUtXG5QYXJhc2l0ZSIsICAiVmVydFBhcmFzaXRlIj0gIlZlcnRlYnJhdGUtXG5QYXJhc2l0ZSIgKSkgKwogIGFubm90YXRlKCd0ZXh0JywgeCA9IDAuOTMsIHkgPSAxOjcgKyAwLjE1LCBsYWJlbD0gcGFzdGUoIml0YWxpYyhrKT09IiwgcmVzX3N5bWJpb250X3RheF9zeW1iaW9zaXMxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwgMSkpICsKICB0aGVtZShsZWdlbmQuZGlyZWN0aW9uPSJob3Jpem9udGFsIikgKwogICN0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gIndoaXRlIiwgY29sb3VyID0gImJsYWNrIikpICsKICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCwgY29sb3VyID0iYmxhY2siLCBoanVzdCA9IDAuNSwgYW5nbGUgPSA5MCkpICsKICAgICMgcHV0dGluZyBwaWN0dXJlcyBpbgogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX211dHVhbGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDAuNiwgeW1heCA9IDEuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX21pY3JvYmVfcGFyYXNpdGUpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BhcmFzaXRpc20pLHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDEuNiwgeW1heCA9IDIuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGxhbnRfcGFyYXNpdGUpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wbGFudF9wYXJhc2l0ZSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGFyYXNpdGlzbSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gNC42LCB5bWF4ID0gNS4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9tdXR1YWxpc20pLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSA0LjYsIHltYXggPSA1LjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX2ludmVydGVicmF0ZV9wYXJhc2l0ZSksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDUuNiwgeW1heCA9IDYuMikgKyAKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BhcmFzaXRpc20pLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSA1LjYsIHltYXggPSA2LjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gNi42LCB5bWF4ID0gNy4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wYXJhc2l0aXNtKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gNi42LCB5bWF4ID0gNy4yKSAKCmZpZ19zeW1iaW9udF90YXhfc3ltYmlvc2lzCmBgYAoKKipGaWd1cmUgUzMuNDoqKiBBbiBvcmNoYXJkIHBsb3Qgc2hvd2luZyBncm91cC13aXNlIG1lYW5zICh0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgYHN5bWJpb250X3RheF9zeW1iaW9zaXNgKSB3aXRoIHRoZWlyIDk1JSBjb25maWRlbmNlIGludGVydmFscyAodGhpY2sgbGluZXMpIGFuZCA5NSUgcHJlZGljdGlvbiBpbnRlcnZhbHMgKHRoaW4gbGluZXMpLCB3aXRoIG9ic2VydmVkIGVmZmVjdCBzaXplcyBiYXNlZCBvbiB2YXJpb3VzIHNhbXBsZSBzaXplcy4KClNwbGl0dGluZyBzeW1iaW9udCB0YXhvbm9teSBieSBtb2RlIG9mIHN5bWJpb3NpcyByZXZlYWxlZCBtdWNoIGxlc3MgdmFyaWF0aW9uLCBleGNlcHQgZm9yIGhpZ2hlciBjb25ncnVlbmNlIGV4aGliaXRlZCBieSBjb3BoeWxvZ2VuaWVzIGludm9sdmluZyBhIHBsYW50IHN5bWJpb250IChpbnN0YW5jZXMgb2Ygd2hpY2ggYXJlIHJlbGF0aXZlbHkgcmFyZSksIGFuZCB0aGUgZmluZGluZyB0aGF0IGNvcGh5bG9nZW5pZXMgaW52b2x2aW5nIGEgbWljcm9iaWFsIG11dHVhbGlzdCBzeW1iaW9udCBhcmUgc2xpZ2h0bHkgbW9yZSBjb25ncnVlbnQgdGhhbiB0aGUgcmVtYWluaW5nIGNhdGVnb3JpZXMuCgoKIyMjIyBUaGUgY29tYmluZWQgZWZmZWN0IG9mIGhvc3QgYW5kIHN5bWJpb250IHRheGEKCmBgYHtyfQojIHJlb3JkZXJpbmcKZGF0JGhvc3Rfc3ltYmlvbnRfdGF4IDwtIGZhY3RvcihkYXQkaG9zdF9zeW1iaW9udF90YXgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiTWljcm9iZUludmVydCIsICJNaWNyb2JlTWljcm9iZSIsICJNaWNyb2JlUGxhbnQiLCJQbGFudEludmVydCIsICJQbGFudE1pY3JvYmUiLCAiSW52ZXJ0SW52ZXJ0IiwgIkludmVydE1pY3JvYmUiLCAiSW52ZXJ0UGxhbnQiLCAiVmVydEludmVydCIsICJWZXJ0TWljcm9iZSIsICJWZXJ0VmVydCIpKQoKIyBtZXRhLXJlZ3Jlc3Npb246IG11bHRpcGxlIGludGVyY2VwdHMKbXJfaG9zdF9zeW1iaW9udF90YXgxIDwtIHJtYS5tdih5aSA9IFpyLCAKICAgICAgICAgICAgICAgICAgICAgICBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBob3N0X3N5bWJpb250X3RheCAtIDEsIAogICAgICAgICAgICAgICAgICAgICAgIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiMgIyBtZXRhLXJlZ3Jlc3Npb246IGNvbnRyYXN0cyB4IDEwCiMgZ2V0dGluZyB0aGUgbGV2ZWwgbmFtZXMgb3V0CmxldmVsX25hbWVzIDwtIGxldmVscyhkYXQkaG9zdF9zeW1iaW9udF90YXgpCgojIGhlbHBlciBmdW5jdGlvbiB0byBydW4gbWV0YWZvciBtZXRhLXJlZ3Jlc3Npb24KcnVuX3JtYSA8LSBmdW5jdGlvbihuYW1lKSB7CiAgcm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHJlbGV2ZWwoaG9zdF9zeW1iaW9udF90YXgsIHJlZiA9IG5hbWUpLCAKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIAogICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBkYXQpCn0KCiMgcmVzdWx0cyBvZiBtZXRhLXJlZ3Jlc3Npb24gaW5jbHVkaW5nIGFsbCBjb250cmFzdCByZXN1bHRzOyB0YWtpbmcgdGhlIGxhc3QgbGV2ZWwgb3V0IChbLWxlbmd0aChsZXZlbF9uYW1lcyldKQptcl9ob3N0X3N5bWJpb250X3RheCA8LSBtYXAobGV2ZWxfbmFtZXNbLWxlbmd0aChsZXZlbF9uYW1lcyldLCBydW5fcm1hKQoKYGBgCgojIyMjIFRhYmxlIFMzLjExClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChlc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYGhvc3Rfc3ltYmlvbnRfdGF4YC4gIE5vdGUgdGhhdCBgbXVgIG1lYW5zIHRoZSBncm91cCBtZWFuIHdoaWxlIGBiZXRhYCByZXByZXNlbnRzIHRoZSBjb250cmFzdCBiZXR3ZWVuIHR3byBncm91cHMgaW4gdGhlIFVuaXQgY29sdW1uLgpgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX2hvc3Rfc3ltYmlvbnRfdGF4MSA8LSBSMihtcl9ob3N0X3N5bWJpb250X3RheDEpCgojIGdldHRpbmcgZXN0aW1hdGVzCnJlc19ob3N0X3N5bWJpb250X3RheDEgPC0gZ2V0X2VzdChtcl9ob3N0X3N5bWJpb250X3RheDEsIG1vZCA9ICJob3N0X3N5bWJpb250X3RheCIpCnJlc19ob3N0X3N5bWJpb250X3RheCA8LSBtYXAobXJfaG9zdF9zeW1iaW9udF90YXgsIH4gZ2V0X2VzdCgueCwgbW9kID0gImhvc3Rfc3ltYmlvbnRfdGF4IikpCgojIGEgbGlzdCBvZiB0aGUgbnVtYmVycyB0byB0YWtlIG91dCB1bm5lY2Vzc2FyeSBjb250cmFzdHMKY29udHJhX2xpc3QgPC0gTWFwKHNlcSwgZnJvbT0xLCB0bz0xOjEwKQoKIyB5b3UgbmVlZCB0byBmbGF0dGVuIHR3aWNlOiBmaXJzdCB0byBtYWtlIGl0IGEgbGlzdCBhbmQgbWFrZSBpdCBhIHZlY3Rvcgplc3RpbWF0ZXMgPC0gbWFwMihyZXNfaG9zdF9zeW1iaW9udF90YXgsIGNvbnRyYV9saXN0LCB+LnhbLSgueSksImVzdGltYXRlIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKCmxvd2VyQ0xzIDwtIG1hcDIocmVzX2hvc3Rfc3ltYmlvbnRfdGF4LCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJsb3dlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKCnVwcGVyQ0xzIDwtIG1hcDIocmVzX2hvc3Rfc3ltYmlvbnRfdGF4LCBjb250cmFfbGlzdCwgfi54Wy0oLnkpLCJ1cHBlckNMIl0pICU+JSBmbGF0dGVuKCkgJT4lIGZsYXR0ZW5fZGJsKCkKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKGFzLmNoYXJhY3RlcihyZXNfaG9zdF9zeW1iaW9udF90YXgxJG5hbWUpLCBjb250X2dlbihyZXNfaG9zdF9zeW1iaW9udF90YXgxJG5hbWUpKSwKICBFc3RpbWF0ZSA9IGMocmVzX2hvc3Rfc3ltYmlvbnRfdGF4MSRlc3RpbWF0ZSwgZXN0aW1hdGVzKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19ob3N0X3N5bWJpb250X3RheDEkbG93ZXJDTCxsb3dlckNMcyksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX2hvc3Rfc3ltYmlvbnRfdGF4MSR1cHBlckNMLHVwcGVyQ0xzKSwKICBgVlthdXRob3JzXWAgPSBjKG1yX2hvc3RfdGF4X3N5bWJpb3NpczEkc2lnbWEyLCAgcmVwKE5BLCAoMTEgKyBjaG9vc2UoMTEsMikpLSAxKSksCiAgYFIyYCA9IGMocjJfaG9zdF9zeW1iaW9udF90YXgxWzFdLCByZXAoTkEsICgxMSArIGNob29zZSgxMSwgMikpLSAxKSkpICU+JSBrYWJsZSgiaHRtbCIsICBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIsIGhlaWdodCA9ICIzMDBweCIpCmBgYAojIyMjIEZpZ3VyZSBTMy41CgpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDEwfQojIGNvbG91ciBsaXN0CiNjb2xvdXJfbHMgPC0gYygiIzAwMDAwMCIsICIjRTY5RjAwIiwgIiM1NkI0RTkiLCAiIzAwOUU3MyIsICAiI0YwRTQyMiIsICAiIzAwNzJCMiIsICAiI0Q1NUUwMCIsICIjQ0M3OUE3IiwgIiMwMDAwOEIiLCAiIzhCMEE1MCIsICIjNTRGRjlGIiwgIiM5OTk5OTkiKQoKIyBhZGRpbmcgc2FtcGxlIHNpemUgKGspIGZvciBlYWNoIGNhdGVnb3J5CmtfaG9zdF9zeW1iaW9udF90YXggPC0gZGF0ICU+JSBncm91cF9ieShob3N0X3N5bWJpb250X3RheCkgJT4lIGNvdW50KCkKIyBnZXR0aW5nIGVzdGltYXRlcyBhbmQgcHJlZGljaXRvbnMKcHJlZF9ob3N0X3N5bWJpb250X3RheCA8LSBnZXRfcHJlZChtcl9ob3N0X3N5bWJpb250X3RheDEsIG1vZCA9ICJob3N0X3N5bWJpb250X3RheCIpIApyZXNfaG9zdF9zeW1iaW9udF90YXgxIDwtIGxlZnRfam9pbihyZXNfaG9zdF9zeW1iaW9udF90YXgxLCBrX2hvc3Rfc3ltYmlvbnRfdGF4LCBieSA9ICBjKCJuYW1lIiA9ICJob3N0X3N5bWJpb250X3RheCIpKSAgJT4lIGxlZnRfam9pbihwcmVkX2hvc3Rfc3ltYmlvbnRfdGF4KQojcmVzX3N5bWJpb3NpczEgCiMgZHJhd2luZyBhIGZ1bm5lbCBwbG90IC0gZmlnIDJiCmZpZ19ob3N0X3N5bWJpb250X3RheCA8LSBnZ3Bsb3QoZGF0YSA9IHJlc19ob3N0X3N5bWJpb250X3RheDEsIGFlcyh4ID0gdGFuaChlc3RpbWF0ZSksIHkgPSBuYW1lKSkgKwogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9YygtMSwgMSksIGJyZWFrcyA9IHNlcSgtMSwgMSwgYnkgPSAwLjIpICkgKwogIGdlb21fcXVhc2lyYW5kb20oZGF0YSA9IGRhdCAlPiUgZmlsdGVyKCFpcy5uYShob3N0X3N5bWJpb250X3RheCkpLCAKICAgICAgICAgICAgICAgICAgIGFlcyh4PSB0YW5oKFpyKSwgeSA9IGhvc3Rfc3ltYmlvbnRfdGF4LCBzaXplID0gKCgxL1ZacikgKyAzKSwgY29sb3VyID0gaG9zdF9zeW1iaW9udF90YXgpLCBncm91cE9uWCA9IEZBTFNFLCBhbHBoYT0wLjQpICsgCiAgIyA5NSAlcHJlY2l0aW9uIGludGVydmFsIChQSSkKICBnZW9tX2Vycm9yYmFyaChhZXMoeG1pbiA9IHRhbmgobG93ZXJQUiksIHhtYXggPSB0YW5oKHVwcGVyUFIpKSwgIGhlaWdodCA9IDAsIHNob3cubGVnZW5kID0gRiwgc2l6ZSA9IDAuNSwgYWxwaGEgPSAwLjYpICsKICAjIDk1ICVDSQogIGdlb21fZXJyb3JiYXJoKGFlcyh4bWluID0gdGFuaChsb3dlckNMKSwgeG1heCA9IHRhbmgodXBwZXJDTCkpLCAgaGVpZ2h0ID0gMCwgc2hvdy5sZWdlbmQgPSBGLCBzaXplID0gMS4yKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgbGluZXR5cGUgPSAyLCBjb2xvdXIgPSAiYmxhY2siLCBhbHBoYSA9IDAuMykgKwogICMgY3JlYXRpbmcgZG90cyBhbmQgZGlmZmVyZW50IHNpemUgKGJlZS1zd2FybSBhbmQgYnViYmxlcykKICBnZW9tX3BvaW50KGFlcyhmaWxsID0gbmFtZSksIHNpemUgPSAzLCBzaGFwZSA9IDIxKSArICMKICAjIHNldHRpbmcgY29sb3VycwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSAgYygiTWljcm9iZUludmVydCIgPSBjb2xvdXJfbHNbMV0sICAiTWljcm9iZU1pY3JvYmUiPSBjb2xvdXJfbHNbMl0sICJNaWNyb2JlUGxhbnQiID0gY29sb3VyX2xzWzNdLCAiUGxhbnRJbnZlcnQiID0gY29sb3VyX2xzWzRdLCJQbGFudE1pY3JvYmUiID0gY29sb3VyX2xzWzVdLCAiSW52ZXJ0SW52ZXJ0IiAgPSBjb2xvdXJfbHNbNl0sICAiSW52ZXJ0TWljcm9iZSIgPSBjb2xvdXJfbHNbN10sICJJbnZlcnRQbGFudCIgPSBjb2xvdXJfbHNbOF0sIlZlcnRJbnZlcnQiICA9IGNvbG91cl9sc1s5XSwgIlZlcnRNaWNyb2JlIj0gY29sb3VyX2xzWzEwXSwiVmVydFZlcnQiICA9IGNvbG91cl9sc1sxMV0pKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTWljcm9iZUludmVydCIgPSBjb2xvdXJfbHNbMV0sICAiTWljcm9iZU1pY3JvYmUiPSBjb2xvdXJfbHNbMl0sICJNaWNyb2JlUGxhbnQiID0gY29sb3VyX2xzWzNdLCAiUGxhbnRJbnZlcnQiID0gY29sb3VyX2xzWzRdLCJQbGFudE1pY3JvYmUiID0gY29sb3VyX2xzWzVdLCAiSW52ZXJ0SW52ZXJ0IiAgPSBjb2xvdXJfbHNbNl0sICAiSW52ZXJ0TWljcm9iZSIgPSBjb2xvdXJfbHNbN10sICJJbnZlcnRQbGFudCIgPSBjb2xvdXJfbHNbOF0sIlZlcnRJbnZlcnQiICA9IGNvbG91cl9sc1s5XSwgIlZlcnRNaWNyb2JlIj0gY29sb3VyX2xzWzEwXSwiVmVydFZlcnQiICA9IGNvbG91cl9sc1sxMV0pKSArCiAgc2NhbGVfeV9kaXNjcmV0ZShsYWJlbHMgPSBjKCJNaWNyb2JlSW52ZXJ0IiA9ICJNaWNyb2JlLVxuSW52ZXJ0ZWJyYXRlIiwgICJNaWNyb2JlTWljcm9iZSI9ICJNaWNyb2JlLVxuTWljcm9iZSIsICJNaWNyb2JlUGxhbnQiID0gIk1pY3JvYmUtXG5QbGFudCIsICJQbGFudEludmVydCIgPSAiUGxhbnQtXG5JbnZlcnRlYnJhdGUiLCJQbGFudE1pY3JvYmUiID0gIlBsYW50LVxuTWljcm9iZSIsICJJbnZlcnRJbnZlcnQiICA9ICJJbnZlcnRlYnJhdGVcbkludmVydGVicmF0ZSIsICAiSW52ZXJ0TWljcm9iZSIgPSAiSW52ZXJ0ZWJyYXRlLVxuTWljcm9iZSIsICJJbnZlcnRQbGFudCIgPSAiSW52ZXJ0ZWJyYXRlLVxuUGxhbnQiLCJWZXJ0SW52ZXJ0IiAgPSAiVmVydGVicmF0ZS1cbkludmVydGVicmF0ZSIsICJWZXJ0TWljcm9iZSI9ICJWZXJ0ZWJyYXRlLVxuTWljcm9iZSIsICJWZXJ0VmVydCIgID0gIlZlcnRlYnJhdGUtXG5WZXJ0ZWJyYXRlIikpICsKICBhbm5vdGF0ZSgndGV4dCcsIHggPSAwLjkzLCB5ID0gMToxMSArIDAuMTUsIGxhYmVsPSBwYXN0ZSgiaXRhbGljKGspPT0iLCByZXNfaG9zdF9zeW1iaW9udF90YXgxJG4pLCBwYXJzZT1UUlVFLCBoanVzdCA9ICJsZWZ0Iiwgc2l6ZT0zLjUpICsKICBsYWJzKHggPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhyKSwgIiAoY29ycmVsYXRpb24pIikpLCB5ID0gIiIsIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSApICsKICBndWlkZXMoZmlsbCA9ICJub25lIiwgY29sb3VyID0gIm5vbmUiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSBjKDAsIDEpLCBsZWdlbmQuanVzdGlmaWNhdGlvbiA9IGMoMCwxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgKwogICAgIyBwdXR0aW5nIHBpY3R1cmVzIGluCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9taWNyb2JlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9pbnZlcnRlYnJhdGVfcGFyYXNpdGUpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSAwLjYsIHltYXggPSAxLjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9taWNyb2JlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSAxLjYsIHltYXggPSAyLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX21pY3JvYmVfcGFyYXNpdGUpLHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDEuNiwgeW1heCA9IDIuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gMi42LCB5bWF4ID0gMy4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGxhbnRfcGFyYXNpdGUpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSAyLjYsIHltYXggPSAzLjIpICsgCiAgIwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfcGxhbnRfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDMuNiwgeW1heCA9IDQuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gMy42LCB5bWF4ID0gNC4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9wbGFudF9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gNC42LCB5bWF4ID0gNS4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9taWNyb2JlX3BhcmFzaXRlKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gNC42LCB5bWF4ID0gNS4yKSArCiAgIwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSA1LjYsIHltYXggPSA2LjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9pbnZlcnRlYnJhdGVfcGFyYXNpdGUpLCB4bWluID0gLTAuOSwgeG1heCA9IC0wLjcsIHltaW4gPSA1LjYsIHltYXggPSA2LjIpICsgCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV9pbnZlcnRlYnJhdGVfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDYuNiwgeW1heCA9IDcuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDYuNiwgeW1heCA9IDcuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX2hvc3QpLCB4bWluID0gLTEuMSwgeG1heCA9IC0wLjksIHltaW4gPSA3LjYsIHltYXggPSA4LjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3BsYW50X3BhcmFzaXRlKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gNy42LCB5bWF4ID0gOC4yKSArCiAgIwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfdmVydGVicmF0ZV9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gOC42LCB5bWF4ID0gOS4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfaW52ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gOC42LCB5bWF4ID0gOS4yKSArIAogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfdmVydGVicmF0ZV9ob3N0KSwgeG1pbiA9IC0xLjEsIHhtYXggPSAtMC45LCB5bWluID0gOS42LCB5bWF4ID0gMTAuMikgKwogIGFubm90YXRpb25fY3VzdG9tKHJhc3Rlckdyb2IoaW1hZ2VfbWljcm9iZV9wYXJhc2l0ZSksIHhtaW4gPSAtMC45LCB4bWF4ID0gLTAuNywgeW1pbiA9IDkuNiwgeW1heCA9IDEwLjIpICsKICBhbm5vdGF0aW9uX2N1c3RvbShyYXN0ZXJHcm9iKGltYWdlX3ZlcnRlYnJhdGVfaG9zdCksIHhtaW4gPSAtMS4xLCB4bWF4ID0gLTAuOSwgeW1pbiA9IDEwLjYsIHltYXggPSAxMS4yKSArCiAgYW5ub3RhdGlvbl9jdXN0b20ocmFzdGVyR3JvYihpbWFnZV92ZXJ0ZWJyYXRlX3BhcmFzaXRlKSwgeG1pbiA9IC0wLjksIHhtYXggPSAtMC43LCB5bWluID0gMTAuNiwgeW1heCA9IDExLjIpCgoKZmlnX2hvc3Rfc3ltYmlvbnRfdGF4CmBgYAoKKipGaWd1cmUgUzMuNToqKiBBbiBvcmNoYXJkIHBsb3Qgc2hvd2luZyB0aGUgZ3JvdXAtd2lzZSBtZWFucyAodGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlIGBob3N0X3N5bWJpb250X3RheGApIHdpdGggdGhlaXIgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzICh0aGljayBsaW5lcykgYW5kIDk1JSBwcmVkaWN0aW9uIGludGVydmFscyAodGhpbiBsaW5lcyksIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLgoKIyMjIE1vZGVsIHNlbGVjdGlvbiAobXVsdGktcHJlZGljdG9yIG1vZGVsKQoKSGVyZSB3ZSBidWlsZCB0aGUgYmVzdCBtb2RlbCB2aWEgYW4gQUlDYyBiYXNlZCBtb2RlbCBzZWxlY3Rpb24gbWV0aG9kIGltcGxlbWVudGVkIGluIHRoZSBSIHBhY2thZ2UgYE11TWluYFtAYmFydG9uMjAwOW11bWluXS4gRm9yIHRoZSBmdWxsIG1vZGVsLCB3ZSBoYWQgNiB2YXJpYWJsZXM6IGBzeW1iaW9zaXNgLCBgaG9zdF90YXhfYnJvYWRgLCBgc3ltYmlvbnRfdGF4X2Jyb2FkYCwgYG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkYCwgYGVuZG9fb3JfZWN0b2AsICYgYGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pYC4gV2UgZGlkIG5vdCB1c2UgYGxvZyhob3N0X3JhbmdlX3RheG9ub21pY19icmVhZHRoKWAgYXMgaXQgaXMgY28tbGluZWFyIHdpdGggYGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pYCBhbmQgYWxzbyBtYW55IG9mIHRoZSBpbnRlcmFjdGlvbiB0ZXJtcy4gCgpgYGB7cn0KIyBjcmVhdGVzIGEgbmV3IGZ1bmN0aW9uIHRvIHJ1biBpbiBNdU1Jbgp1cGRhdGVkLnJtYS5tdiA8LSB1cGRhdGVhYmxlKHJtYS5tdikKI3VwZGF0ZWQucm1hLm12CgojIHRlc3RpbmcgdGhlIG5ldyBmdW5jdGlvbiAKIyB1c2UgbWV0aG9kID0gIk1MIiBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIEFJQwptcl9mdWxsIDwtIHVwZGF0ZWQucm1hLm12KHlpID0gWnIsIAogICAgICAgICAgICAgICAgICAgICAgIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgIG1vZHMgPSB+IHN5bWJpb3NpcyArIAogICAgICAgICAgICAgICAgICAgICAgICAgaG9zdF90YXhfYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgc3ltYmlvbnRfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgIGVuZG9fb3JfZWN0byArCiAgICAgICAgICAgICAgICAgICAgICAgICBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKSwKICAgICAgICAgICAgICAgICAgICAgICB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsCiAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kPSJNTCIsCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGRhdCkKCiM9PT09PT09PT09PT09PT09PT09PT09PT09PT09PQojIyMgYWRkaXRpb25hbCBtZXRob2RzIGZvciAicm1hLm12IiBjbGFzcyAobWFkZSBieSBLYW1pbCBCYXJ0b24pCiMjIyB3ZSBuZWVkIHRoaXMgdG8gcnVuIG1vZGVsIHNlbGVjdGlvbiB3aXRoIHJtYS5tdiBpbiBNdU1JbgojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KZm9ybXVsYS5ybWEubXYgPC0gZnVuY3Rpb24gKHgsIC4uLikgcmV0dXJuKGV2YWwoZ2V0Q2FsbCh4KSRtb2RzKSkKCm1ha2VBcmdzLnJtYS5tdiA8LQogIGZ1bmN0aW9uIChvYmosIHRlcm1OYW1lcywgY29tYiwgb3B0LCAuLi4pIHsKICAgIHJldCA8LSBNdU1Jbjo6Om1ha2VBcmdzLmRlZmF1bHQob2JqLCB0ZXJtTmFtZXMsIGNvbWIsIG9wdCkKICAgIG5hbWVzKHJldClbMUxdIDwtICJtb2RzIgogICAgcmV0CiAgfQoKbm9icy5ybWEubXYgPC0KICBmdW5jdGlvbiAob2JqZWN0LCAuLi4pCiAgICBhdHRyKGxvZ0xpayhvYmplY3QpLCAibmFsbCIpCgpjb2VmVGFibGUucm1hLm12IDwtIGZ1bmN0aW9uIChtb2RlbCwgLi4uKQogIE11TUluOjo6Lm1ha2VDb2VmVGFibGUobW9kZWwkYiwgbW9kZWwkc2UsIGNvZWZOYW1lcyA9IHJvd25hbWVzKG1vZGVsJGIpKQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KCiMgdGVzdGluZyBkcmVkZ2UKI2RyZWRnZShmdWxsLm1vZGVsLCBldmFsdWF0ZT1GKSAjIHNob3cgYWxsIGNhbmRpZGF0ZSBtb2RlbHMKIyBuID0gMzIgbW9kZWwgZXhpc2l0CmNhbmRpZGF0ZXMgPC0gZHJlZGdlKG1yX2Z1bGwpCgojIGRpc3BsYXlzIGRlbHRhIEFJQ2MgPDIKY2FuZGlkYXRlc19haWMyIDwtIHN1YnNldChjYW5kaWRhdGVzLCBkZWx0YSA8IDIpCgojIG1vZGVsIGF2ZXJhZ2luZwojIGl0IHNlZW1zIGxpa2UgbW9kZWxzIGFyZSB1c2luZyB6IHZhbHVlcyByYXRoZXIgdGhhbiB0IHZhbHVlcyAod2hpY2ggd2lsbCBiZSBPSykKbXJfYXZlcmFnZWRfYWljMiA8LSBzdW1tYXJ5KG1vZGVsLmF2ZyhjYW5kaWRhdGVzLCAgZGVsdGEgPCAyKSkKCiMgcmVsYXRpdmUgaW1wb3J0YW5jZSBvZiBlYWNoIHByZWRpY3RvcgppbXBvcnRhbmNlIDwtIGltcG9ydGFuY2UoY2FuZGlkYXRlcykKCiMgdXNlIFJFTUwgaWYgbm90IGZvciBtb2RlbCBjb21wYXJpc2lvbgptb2RlbDEgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+ICBob3N0X3RheF9icm9hZCAgKyAKICAgICAgICAgICAgICAgICAgIG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICsgc3ltYmlvc2lzLCB0ZXN0ID0gInQiLAogICAgICAgICAgICAgICAgIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIG1ldGhvZD0iUkVNTCIsIGRhdGEgPSBkYXQpCm1vZGVsMiA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgbW9kcyA9IH4gIGhvc3RfdGF4X2Jyb2FkICsgCiAgICAgICAgICAgICAgICAgICBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBtZXRob2Q9IlJFTUwiLCBkYXRhID0gZGF0KQptb2RlbDMgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+ICBob3N0X3RheF9icm9hZCArIAogICAgICAgICAgICAgICAgICAgbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbykgKwogICAgICAgICAgICAgICAgICAgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKyBzeW1iaW9zaXMsIHRlc3QgPSAidCIsCiAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgbWV0aG9kPSJSRU1MIiwgZGF0YSA9IGRhdCkKbW9kZWw0IDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCBtb2RzID0gfiAgaG9zdF90YXhfYnJvYWQgKwogICAgICAgICAgICAgICAgICAgIGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pICsgCiAgICAgICAgICAgICAgICAgICBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgdGVzdCA9ICJ0IiwKICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBtZXRob2Q9IlJFTUwiLCBkYXRhID0gZGF0KQpgYGAKCiMjIyMgVGFibGUgMy4xMgpUaGUgdG9wIDQgbW9kZWxzIChvdXQgb2YgMzIgcG9zc2libGUgbW9kZWxzKSB3aXRoaW4gdGhlICRcRGVsdGEkQUlDIGRpZmZlcmVuY2Ugb2YgMiwgYW5kIHdoaWNoIDYgdmFyaWFibGVzOiBgc3ltYmlvc2lzYCwgYGhvc3RfdGF4X2Jyb2FkYCwgYHN5bWJpb250X3RheF9icm9hZGAsIGBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGAsIGBlbmRvX29yX2VjdG9gLCAmIGBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKWAgd2VyZSBpbmNsdWRlZCAoaW5kaWNhdGVkIGJ5ICQrJCk7IG1vZGVsIHdlaWdodHMgKGZvciB0aGUgMiBtb2RlbHMpIGFuZCB0aGUgc3VtIG9mIHdlaWdodHMgZm9yIGVhY2ggb2YgdGhlIHZhcmlhYmxlcyAoZnJvbSB0aGUgMzIgbW9kZWxzKSBhcmUgaW5jbHVkZWQuIAoKYGBge3J9CiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYE1vZGVsICh2YXJpYWJsZSB3ZWlnaHQpYCA9IGMoIk1vZGVsMSIsICJNb2RlbDIiLCAiTW9kZWwzIiwgIk1vZGVsNCIsIihTdW0gb2Ygd2VpZ2h0cykiKSwKICB0cmFuc21pc3Npb24gPSBjKGlmX2Vsc2UoY2FuZGlkYXRlc19haWMyJG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkID09ICIrIiwgIiQrJCIsICJOQSIpLHJvdW5kKGltcG9ydGFuY2VbMV0sMykgKSwKICBob3N0X3RheCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkaG9zdF90YXhfYnJvYWQ9PSAiKyIsICIkKyQiLCAiTkEiKSxyb3VuZChpbXBvcnRhbmNlWzJdLCAzKSksCiAgc3ltYmlvc2lzID0gIGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkc3ltYmlvc2lzPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVszXSwgMykpLAogIGBob3N0X3JhbmdlYCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkYGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pYCA+PSAwLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVs0XSwgMykpLAogIHN5bWJpb250X3RheCA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkc3ltYmlvbnRfdGF4X2Jyb2FkPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVs1XSwgMykpLAogIGVuZG9fb3JfZWN0byA9IGMoaWZfZWxzZShjYW5kaWRhdGVzX2FpYzIkZW5kb19vcl9lY3RvPT0gIisiLCAiJCskIiwgIk5BIikscm91bmQoaW1wb3J0YW5jZVs2XSwgMykpLAogIGRlbHRhX0FJQ2MgPSBjKGNhbmRpZGF0ZXNfYWljMiRkZWx0YSwgTkEpLAogIFdlaWdodCA9IGMoY2FuZGlkYXRlc19haWMyJHdlaWdodCwgTkEpKSAlPiUgCiAga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAoKIyMjIyBNb2RlbCBhdmVyYWdpbmcKCiMjIyMgVGFibGUgMy4xMwpUaGUgYXZlcmFnZSBlc3RpbWF0ZXMgZm9yIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgMiBiZXN0IG1ldGEtcmVncmVzc2lvbiBtb2RlbHMuIE5vdGUgdGhhdCBgbXVgIHNob3dzIHRoZSBvdmVyYWxsIHZhbHVlIGF0IHRoZSBpbnRlcmNlcHQgd2hpbGUgYGJldGFgIHJlcHJlc2VudHMgdGhlIGNvbnRyYXN0IChvciBzbG9wZSkgYmV0d2VlbiB0d28gZ3JvdXBzIGluIHRoZSBVbml0IGNvbHVtbi4KYGBge3J9CgojIGdldHRpbmcgYXZlcmFnZWQgUjIgYW5kIHZhcmlhbmNlIGNvbXBvbmVudHMgbm90IHByb3ZpZGVkIGJ5IHRoZSBNdU1JbiBwYWNrYWdlCmF2ZXJhZ2Vfc2lnbWEyIDwtIHdlaWdodGVkLm1lYW4oeCA9IGMobW9kZWwxJHNpZ21hMiwgbW9kZWwyJHNpZ21hMiwgbW9kZWwzJHNpZ21hMiwgbW9kZWw0JHNpZ21hMiksIHcgPSBjYW5kaWRhdGVzX2FpYzIkd2VpZ2h0KQphdmVyYWdlX1IyIDwtIHdlaWdodGVkLm1lYW4oeCA9IGMoUjIobW9kZWwxKVsxXSwgUjIobW9kZWwyKVsxXSwgUjIobW9kZWwzKVsxXSwgUjIobW9kZWw0KVsxXSkgLCB3ID0gY2FuZGlkYXRlc19haWMyJHdlaWdodCkKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKCJJbnRlcmNlcHQgKGJvdGgtTWljcm9iZS1NdXR1YWxpc3QpIiwKICAgICAgICAgICAgICAgICAgICAgIk1pY3JvYmUtUGxhbnQiLCAiTWljcm9iZS1JbnZlcnQiLCAiTWljcm9iZS1WZXJ0IiwgCiAgICAgICAgICAgICAgICAgICAgICJob3N0X3JhbmdlIiwiYm90aC1ob3Jpem9udGFsIiwgImJvdGgtdmVydGljYWwiLAogICAgICAgICAgICAgICAgICAgICAiTXV0dWFsaXN0LVBhcmFzaXRlIiksCiAgRXN0aW1hdGUgPSBtcl9hdmVyYWdlZF9haWMyJGNvZWZtYXQuZnVsbFssMV0sCiAgYExvd2VyIENJIFswLjAyNV1gID0gIG1yX2F2ZXJhZ2VkX2FpYzIkY29lZm1hdC5mdWxsWywxXSAtIG1yX2F2ZXJhZ2VkX2FpYzIkY29lZm1hdC5mdWxsWywyXSpxbm9ybSgwLjk3NSksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9ICBtcl9hdmVyYWdlZF9haWMyJGNvZWZtYXQuZnVsbFssMV0gKyBtcl9hdmVyYWdlZF9haWMyJGNvZWZtYXQuZnVsbFssMl0qcW5vcm0oMC45NzUpLAogIGBWW2F1dGhvcnNdYCA9IGMoYXZlcmFnZV9zaWdtYTIsIHJlcChOQSw3KSksCiAgYFIyYCA9IGMoYXZlcmFnZV9SMiwgcmVwKE5BLDcpKSkgJT4lIAogIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKQpgYGAKCiMjIEFwcGVuZGl4IFM0OiBQdWJsaWNhdGlvbiBCaWFzIEFuYWx5c2lzCgpIZXJlLCB3ZSBjb25kdWN0ZWQgMyBraW5kcyBvZiBwdWJsaWNhdGlvbiBiaWFzIGFuYWx5c2VzOiAxKSBjb250b3VyLWVuaGFuY2VkIGZ1bm5lbCBwbG90cyBbQHBldGVyczIwMDhjb250b3VyXSBvZiByZXNpZHVhbHMgW0BlZ2dlcjE5OTdiaWFzOyBAbmFrYWdhd2EyMDEybWV0aG9kb2xvZ2ljYWxdLCAyKSBhIHR5cGUgb2YgRWdnZXIgcmVncmVzc2lvbiBbQGVnZ2VyMTk5N2JpYXM7IEBtb3Jlbm8yMDA5YXNzZXNzbWVudF0sIGFuZCAzKSBhIHJlZ3Jlc3Npb24tYmFzZWQgdGltZS1sYWcgYmlhcyB0ZXN0IFtAbmFrYWdhd2EyMDEybWV0aG9kb2xvZ2ljYWxdLiAKCiMjIyBGdW5uZWwgcGxvdCAKCkEgbm9ybWFsIGZ1bm5lbCBwbG90IGFzc3VtZXMgaG9tb2dlbmVpdHkgKGkuZS4sICpJKl4yXiA9IDApLiBUaGVyZWZvcmUsIHdlIGNvbnRyb2xsZWQgZm9yIGltcG9ydGFudCBtb2RlcmF0b3JzIChpLmUuLCBgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBgaG9zdF90YXhfYnJvYWRgLCBgbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbylgLCAmIGBzeW1iaW9zaXNgKS4KCiMjIyMgUmVzaWR1YWwgZnVubmVsIHBsb3QgMQoKV2UgZG8gbm90IG9ic2VydmUgbm9ybWFsIHNrZXduZXNzIGluIG91ciBlbmhhbmNlZC1jb3VudGVyIGZ1bm5lbCBwbG90ICgqKlN1cHBsZW1lbnRhcnkgRmlndXJlIDUqKikuIFRoaXMgZnVubmVsIGFzeW1tZXRyeSBzZWVtcyBkaWZmZXJlbnQgZnJvbSBvbmUgY2F1c2VkIGJ5IHB1YmxpY2F0aW9uIGJpYXNbQHBldGVyczIwMDhjb250b3VyXTsgd2UgZG8gbm90IGV4cGVjdCBhICJob2xsb3ciIGluIHRoZSByZWdpb24gd2l0aCBoaWdoIHByZWNpc2lvbiBvciBpLmUuIGludmVyc2Ugc3RhbmRhcmQgZXJyb3IgKDIuNC00KSBhbmQgcmVsYXRpdmUgaGlnaCBlZmZlY3Qgc2l6ZXMgKCpaciogPSAwLjUtMS4wKS4gIFRoZSBmdW5uZWwgYXN5bW1ldHJ5IGlzIG1haW5seSBjYXVzZWQgYnkgdGhlIGJvdW5kYXJ5IGNyZWF0ZWQgYnkgdGhlIG51bWJlciBvZiByYW5kb21pemF0aW9ucyAoc2VlIHRoZSAiU2Vuc2l0aXZpdHkgQW5hbHlzaXMiIHNlY3Rpb24gd2hlcmUgd2UgZGVhbCB3aXRoIHRoaXMgc2tld25lc3MpLgoKIyMjIyBGaWd1cmUgNWEKYGBge3J9CiMgCnJlc19mdW5uZWxfcGxvdCA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RfdGF4X2Jyb2FkICsgbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbykgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeW1iaW9zaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmZ1bm5lbChyZXNfZnVubmVsX3Bsb3QsIHlheGlzID0gInNlaW52IiwgbGV2ZWw9Yyg5MCwgOTUsIDk5KSwgCiAgICAgICB4bGltICA9IGMoLTMsIDQpLCB5bGltID0gYygwLjksIDUuMiksIHhsYWIgPSAiUmVzaWR1YWxzIChjb3JyZWxhdGlvbikiLCB5bGFiID0gIlByZWNpc2lvbiAoMS9TRSkiLAogICAgICAgc2hhZGU9Yygid2hpdGUiLCAiZ3JheTU1IiwgImdyYXk3NSIpLCAKICAgICAgIHJlZmxpbmU9MCwgbGVnZW5kPVRSVUUpCmBgYAoKKipGaWd1cmUgNWE6KiogQSByZXNpZHVhbCBmdW5uZWwgcGxvdCBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gbW9kZWwgd2l0aCBgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBgaG9zdF90YXhfYnJvYWRgLCAmIGBzeW1iaW9zaXNgOyAncmVzaWR1YWwgdmFsdWUnIGlzIG9uICpaciogYW5kICdpbnZlcnNlIHN0YW5kYXJkIGVycm9yJyBpcyBwcmVjaXNpb24gYDEvc3FydChWWnIpYC4KCgojIyMjIFJlc2lkdWFsIGZ1bm5lbCBwbG90IDIKCkZ1cnRoZXIsIEVnZ2VyIHJlZ3Jlc3Npb24gYW5hbHlzZXMgKHNlZSBiZWxvdykgc2hvd2VkIHRoYXQgYHNxcnQoVlpyKWAgKHNhbXBsaW5nIGVycm9ycyBbU0VdIGZvciBlZmZlY3Qgc2l6ZXMpIGFjY291bnRzIGZvciBtdWNoIGhldGVyb2dlbmVpdHksIHNvIHdlIGFkZGVkIHRoYXQgdG8gb3VyIG1vZGVsLiBUaGUgZnVubmVsIGFzeW1tZXRyeSB3ZSBzZWUgaW4gKipTdXBwbGVtZW50YXJ5IEZpZ3VyZSA2KiogKGlmIGFueSkgaXMgbXVjaCBsZXNzIHNldmVyZSB0aGFuIHRoYXQgaW4gKipTdXBwbGVtZW50YXJ5IEZpZ3VyZSA1KiouIAoKIyMjIyBGaWd1cmUgNWIKYGBge3J9CiMgCnJlc19mdW5uZWxfcGxvdDIgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4gc3FydChWWnIpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9zdF90YXhfYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxvZyhob3N0X3JhbmdlX2xpbmtfcmF0aW8pICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeW1iaW9zaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmZ1bm5lbChyZXNfZnVubmVsX3Bsb3QyLCB5YXhpcyA9ICJzZWludiIsIGxldmVsPWMoOTAsIDk1LCA5OSksCiAgICAgICB4bGltICA9IGMoLTMsIDQpLCB5bGltID0gYygwLjksIDUuMiksIHhsYWIgPSAiUmVzaWR1YWxzIChjb3JyZWxhdGlvbikiLCB5bGFiID0gIlByZWNpc2lvbiAoMS9TRSkiLAogICAgICAgc2hhZGU9Yygid2hpdGUiLCAiZ3JheTU1IiwgImdyYXk3NSIpLCByZWZsaW5lPTAsIGxlZ2VuZD1UUlVFKQpgYGAKCioqRmlndXJlIDViOioqIEEgcmVzaWR1YWwgZnVubmVsIHBsb3QgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIG1vZGVsIHdpdGggYHNxcnQoVlpyKWAsIGBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGAsIGBob3N0X3RheF9icm9hZGAsIGBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKWAsICYgYHN5bWJpb3Npc2A7ICdyZXNpZHVhbCB2YWx1ZScgaXMgb24gKlpyKiBhbmQgJ2ludmVyc2Ugc3RhbmRhcmQgZXJyb3InIGlzIHByZWNpc2lvbiBgMS9zcXJ0KFZacilgLgoKIyMjIyBQdXR0aW5nIHRvZ2V0aGVyIEZpZ3VyZSA1CgpgYGB7ciwgZmlnLndpZHRoPTE0LCBmaWcuaGVpZ2h0PSA2fQojIGJ1aWxkaW5nIGZpZyAzIHVzaW5nIHBhdGNod29yawoKcGFyKG1mcm93ID0gYygxLDIpKQpmdW5uZWwocmVzX2Z1bm5lbF9wbG90LCB5YXhpcyA9ICJzZWludiIsIGxldmVsPWMoOTAsIDk1LCA5OSksIAogICAgICAgeGxpbSAgPSBjKC0zLCA0KSwgeWxpbSA9IGMoMC45LCA1LjIpLCB4bGFiID0gIlJlc2lkdWFscyAoY29ycmVsYXRpb24pIiwgeWxhYiA9ICJQcmVjaXNpb24gKDEvU0UpIiwKICAgICAgIHNoYWRlPWMoIndoaXRlIiwgImdyYXk1NSIsICJncmF5NzUiKSwgCiAgICAgICByZWZsaW5lPTAsIGxlZ2VuZD1UUlVFKQptdGV4dCgiYSIsIHNpZGUgPSAzLCBjZXggPSAxLjUsIGxpbmUgPSAxLCBhZGogPSAwKQpmdW5uZWwocmVzX2Z1bm5lbF9wbG90MiwgeWF4aXMgPSAic2VpbnYiLCBsZXZlbD1jKDkwLCA5NSwgOTkpLAogICAgICAgeGxpbSAgPSBjKC0zLCA0KSwgeWxpbSA9IGMoMC45LCA1LjIpLCB4bGFiID0gIlJlc2lkdWFscyAoY29ycmVsYXRpb24pIiwgeWxhYiA9ICJQcmVjaXNpb24gKDEvU0UpIiwKICAgICAgIHNoYWRlPWMoIndoaXRlIiwgImdyYXk1NSIsICJncmF5NzUiKSwgcmVmbGluZT0wLCBsZWdlbmQ9VFJVRSkKbXRleHQoImIiLCBzaWRlID0gMywgY2V4ID0gMS41LCBsaW5lID0gMSwgYWRqID0gMCkKCmBgYAoKIyMjIEVnZ2VyJ3MgcmVncmVzc2lvbgoKV2UgYXBwbGllZCBFZ2dlcidzIHJlZ3Jlc3Npb24gdG8gdGVzdCB3aGV0aGVyIHRoZSBmdW5uZWwgYXN5bW1ldHJpZXMgd2Ugb2JzZXJ2ZSBpbiBvdXIgZnVubmVsIHBsb3RzIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IG9yIG5vdC4gCgojIyMjIFVuaXZhcmlhdGUgRWdnZXIncyByZWdyZXNzaW9uCgpUaGUgdGVzdCAob3IgYHNxcnQoVlpyKWApIGlzIHNpZ25pZmljYW50LiBIb3dldmVyLCBhcyBtZW50aW9uZWQgYWJvdmUsIHRoaXMgaXMgZHVlIHRvIHRoZSBib3VuZGFyeSBjcmVhdGVkIGJ5IHRoZSBudW1iZXIgb2YgcmFuZG9taXphdGlvbnM7IHRoaXMgYm91bmRhcnkgY2FuIGJlIHNlZW4gaW4gKipGaWd1cmUgUzQuMSoqIGJlbG93LiAgCgpgYGB7cn0KIyAKZWdnZXJfcmVncmVzc2lvbl91bmkgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+IHNxcnQoVlpyKSwgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmBgYAoKIyMjIyBUYWJsZSBTNC4xClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHNxcnQoVlpyKWAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pIDwtIFIyKGVnZ2VyX3JlZ3Jlc3Npb25fdW5pKQoKIyBnZXR0aW5nIGVzdGltYXRlczogbmFtZSBkb2VzIG5vdCB3b3JrIGZvciBzbG9wZXMKcmVzX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pIDwtIGdldF9lc3QoZWdnZXJfcmVncmVzc2lvbl91bmksIG1vZCA9ICJzcXJ0KFZacikiKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoIkludGVyY2VwdCIsICJzcXJ0KFZacikiKSwKICBFc3RpbWF0ZSA9IGMocmVzX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJGVzdGltYXRlKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKHJlc19lZ2dlcl9yZWdyZXNzaW9uX3VuaSRsb3dlckNMKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhyZXNfZWdnZXJfcmVncmVzc2lvbl91bmkkdXBwZXJDTCksCiAgYFZbYXV0aG9yc11gID0gYyhlZ2dlcl9yZWdyZXNzaW9uX3VuaSRzaWdtYTIsIE5BKSwKICBgUjJgID0gYyhyMl9lZ2dlcl9yZWdyZXNzaW9uX3VuaVsxXSwgTkEpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpCmBgYAojIyMjIEZpZ3VyZSBTNC4xCmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gNH0KcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX3VuaSA8LXByZWRpY3Qucm1hKGVnZ2VyX3JlZ3Jlc3Npb25fdW5pKSAKCiMgcGxvdHRpbmcKCmZpdF9lZ2dlcl9yZWdyZXNzaW9uX3VuaSA8LSAgZGF0ICU+JSAKICBtdXRhdGUoeW1pbiA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl91bmkkY2kubGIsIAogICAgICAgICB5bWF4ID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX3VuaSRjaS51YiwKICAgICAgICAgeW1pbjIgPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJGNyLmxiLAogICAgICAgICB5bWF4MiA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl91bmkkY3IudWIsCiAgICAgICAgIHByZWQgPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fdW5pJHByZWQpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzcXJ0KFZaciksIHkgPSBaciwgc2l6ZSA9ICgxL1ZacikgKyAzKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJncmV5OTAiKSArCiAgI2dlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gIiMwMDcyQjIiKSAgKyAjIG5vdCBxdWl0ZSBzdXJlIHdoeSB0aGlzIGRvZXMgbm90IHdvcmsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4yKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4MiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4KSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArIAogIGdlb21fc21vb3RoKGFlcyh5ID0gcHJlZCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkYXNoZWQiLCBsd2QgPSAwLjUsIGNvbG91ciA9ImJsYWNrIikgKyAgCiAgeWxpbSgtMSwgMikgKyB4bGltKDAuMDUsIDAuNDUpICsKICAjZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzFdXSwgc2xvcGUgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMl1dLCBhbHBoYSA9IDAuNywgbGluZXR5cGUgPSAiZGFzaGVkIiwgc2l6ZSA9IDAuNSkgKwogIGxhYnMoeCA9ICJzcXJ0KHNhbXBsaW5nIHZhcmlhbmNlKSIsIHkgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhaciksICIgKGVmZmVjdCBzaXplKSIpKSwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogICMgdGhlbXNlcwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpdF9lZ2dlcl9yZWdyZXNzaW9uX3VuaQpgYGAKCioqRmlndXJlIFM0LjE6KioKQSBidWJibGUgcGxvdCBzaG93aW5nIGEgcHJlZGljdGVkIHJlZ3Jlc3Npb24gbGluZSBmb3IgdGhlIGNvbnRpbnVvdXMgdmFyaWFibGUgYHNxcnQoVlpyKWAsIGluZGljYXRpbmcgOTUlIGNvbmZpZGVuY2UgcmVnaW9ucyAob3JhbmdlIGRvdHRlZCBsaW5lcykgYW5kIDk1JSBwcmVkaWN0aW9uIHJlZ2lvbnMgKGJsdWUgZG90dGVkIGxpbmVzKSwgd2l0aCBvYnNlcnZlZCBlZmZlY3Qgc2l6ZXMgYmFzZWQgb24gdmFyaW91cyBzYW1wbGUgc2l6ZXMuIAoKCiMjIyMgTXVsdGl2YXJpYXRlIEVnZ2VyIHJlZ3Jlc3Npb24KCldlIGFsc28gY29uZHVjdGVkIGFuIEVnZ2VyIHJlZ3Jlc3Npb24gY29udHJvbGxpbmcgb3RoZXIgaW1wb3J0YW50IG1vZGVyYXRvcnMgKGkuZS4sIGBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGAsIGBob3N0X3RheF9icm9hZGAsIGBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKWAsICYgYHN5bWJpb3Npc2ApLiBBZnRlciBjb250cm9sbGluZyBmb3IgdGhlc2UgdmFyaWFibGVzLCBgc3FydChWWnIpYCBzdGF5cyBzaWduaWZpY2FudC4KCmBgYHtyfQojIAplZ2dlcl9yZWdyZXNzaW9uX211bCA8LSBybWEubXYoeWkgPSBaciwgViA9IFZaciwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RzID0gfiBzcXJ0KFZacikgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nKGhvc3RfcmFuZ2VfbGlua19yYXRpbykgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzeW1iaW9zaXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmFuZG9tID0gfiAxIHwgYXV0aG9ycywgZGF0YSA9IGRhdCkKCmBgYAoKIyMjIyBUYWJsZSBTNC4yClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChFc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgbWV0YS1yZWdyZXNzaW9uIHdpdGggYHNxcnQoVlpyKWAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsIDwtIFIyKGVnZ2VyX3JlZ3Jlc3Npb25fbXVsKQoKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoIkludGVyY2VwdCAoYm90aC1NaWNyb2JlLU11dHVhbGlzdCkiLCAic3FydChWWnIpIiwgImJvdGgtaG9yaXpvbnRhbCIsICJib3RoLXZlcnRpY2FsIiwgCiAgICAgICAgICAgICAgICAgICAgICJNaWNyb2JlLVBsYW50IiwgIk1pY3JvYmUtSW52ZXJ0IiwgIk1pY3JvYmUtVmVydCIsICJob3N0X3JhbmdlIiwgIk11dHVhbGlzdC1QYXJhc2l0ZSIpLAogIEVzdGltYXRlID0gYyhlZ2dlcl9yZWdyZXNzaW9uX211bCRiKSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSBjKGVnZ2VyX3JlZ3Jlc3Npb25fbXVsJGNpLmxiKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyhlZ2dlcl9yZWdyZXNzaW9uX211bCRjaS51YiksCiAgYFZbYXV0aG9yc11gID0gYyhlZ2dlcl9yZWdyZXNzaW9uX211bCRzaWdtYTIsIHJlcChOQSw4KSksCiAgYFIyYCA9IGMocjJfZWdnZXJfcmVncmVzc2lvbl9tdWxbMV0sIHJlcChOQSw4KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCiMjIyMgRmlndXJlIFM0LjIKYGBge3IsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PSA0fQpwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsIDwtcHJlZGljdC5ybWEoZWdnZXJfcmVncmVzc2lvbl9tdWwpIAoKIyBwbG90dGluZwoKZml0X2VnZ2VyX3JlZ3Jlc3Npb25fbXVsIDwtICBkYXQgJT4lIAogIGZpbHRlcighaXMubmEobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpICYgIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSAmICFpcy5uYShzeW1iaW9zaXMpICYgIWlzLm5hKGhvc3RfcmFuZ2VfbGlua19yYXRpbykpICAlPiUgIyBnZXR0aW5nIHJpZGUgb2YgTkEgdmFsdWVzCiAgbXV0YXRlKHltaW4gPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsJGNpLmxiLCAKICAgICAgICAgeW1heCA9IHByZWRfZWdnZXJfcmVncmVzc2lvbl9tdWwkY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX211bCRjci5sYiwKICAgICAgICAgeW1heDIgPSBwcmVkX2VnZ2VyX3JlZ3Jlc3Npb25fbXVsJGNyLnViLAogICAgICAgICBwcmVkID0gcHJlZF9lZ2dlcl9yZWdyZXNzaW9uX211bCRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gc3FydChWWnIpLCB5ID0gWnIsIHNpemUgPSAoMS9WWnIpICsgMykpICsKICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGZpbGwgPSAiZ3JleTkwIikgKwogICNnZW9tX3JpYmJvbihhZXMoeW1pbiA9IHltaW4sIHltYXggPSB5bWF4KSwgZmlsbCA9ICIjMDA3MkIyIikgICsgIyBub3QgcXVpdGUgc3VyZSB3aHkgdGhpcyBkb2VzIG5vdCB3b3JrCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluMiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAgImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heDIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9ICIjMDA3MkIyIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKwogIGdlb21fc21vb3RoKGFlcyh5ID0geW1heCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSIjRDU1RTAwIikgKyAKICBnZW9tX3Ntb290aChhZXMoeSA9IHByZWQpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZGFzaGVkIiwgbHdkID0gMC41LCBjb2xvdXIgPSJibGFjayIpICsgIAogIHlsaW0oLTEsIDIpICsgeGxpbSgwLjA1LCAwLjQ1KSArCiAgI2dlb21fYWJsaW5lKGludGVyY2VwdCA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1sxXV0sIHNsb3BlID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzJdXSwgYWxwaGEgPSAwLjcsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAwLjUpICsKICBsYWJzKHggPSAic3FydChzYW1wbGluZyB2YXJpYW5jZSkiLCB5ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMoWnIpLCAiIChlZmZlY3Qgc2l6ZSkiKSksIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICAjIHRoZW1zZXMKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgpmaXRfZWdnZXJfcmVncmVzc2lvbl9tdWwKYGBgCgoqKkZpZ3VyZSBTNC4yOioqCkEgYnViYmxlIHBsb3Qgc2hvd2luZyBhIHByZWRpY3RlZCBsb2VzcyBsaW5lIGZvciB0aGUgY29udGludW91cyB2YXJpYWJsZSBgc3FydChWWnIpYCAoZ2l2ZW4gdGhlIHZhbHVlcyBvZiB0aGUgb3RoZXIgMyB2YXJpYWJsZXMgaW4gdGhlIG1vZGVsKSwgd2l0aCB0aGVpciA5NSUgY29uZmlkZW5jZSByZWdpb25zIChvcmFuZ2UgZG90dGVkIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gcmVnaW9ucyAoYmx1ZSBkb3R0ZWQgbGluZXMpIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLiBOb3RlIHRoYXQgdGhlIGxpbmVzIGFyZSBub3QgbGluZWFyIGFzIHRoZXNlIGFyZSBiYXNlZCBvbiBtdWx0aXZhcmlhdGUgcHJlZGljdGlvbnMgb2YgdGhlIGRhdGEgcG9pbnRzLiAKCiMjIyBUaW1lLWxhZyBiaWFzCgpXZSBkbyBub3QgZmluZCBhbnkgZXZpZGVuY2Ugb2YgYSB0aW1lLWxhZyBlZmZlY3QgKGEgZGVjbGluZSBpbiB0aGUgbWFnbml0dWRlIG9mIHRoZSBlZmZlY3Qgb3ZlciB0aW1lKSBpbiBlaXRoZXIgdGhlIHVuaXZhcmlhdGUgb3IgbXVsdGl2YXJpYXRlIG1vZGVscyAoKipGaWd1cmUgUzQuWCoqIGFuZCAqKkZpZ3VyZSBTNC5YKiopLgoKIyMjIyBVbml2YXJpYXRlIHRpbWUtbGFnIGJpYXMKYGBge3J9CiMgCnRpbWVfbGFnX2VmZmVjdF91bmkgPC0gcm1hLm12KHlpID0gWnIsIFYgPSBWWnIsIG1vZHMgPSB+IHllYXIsIHJhbmRvbSA9IH4gMSB8IGF1dGhvcnMsIGRhdGEgPSBkYXQpCgpgYGAKCiMjIyMgVGFibGUgUzQuMwpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIG1ldGEtcmVncmVzc2lvbiB3aXRoIGB5ZWFyYC4gCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfdGltZV9sYWdfZWZmZWN0X3VuaSA8LSBSMih0aW1lX2xhZ19lZmZlY3RfdW5pKQoKIyBnZXR0aW5nIGVzdGltYXRlczogbmFtZSBkb2VzIG5vdCB3b3JrIGZvciBzbG9wZXMKcmVzX3RpbWVfbGFnX2VmZmVjdF91bmkgPC0gZ2V0X2VzdCh0aW1lX2xhZ19lZmZlY3RfdW5pLCBtb2QgPSAieWVhciIpCgojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYygiSW50ZXJjZXB0IiwgIlllYXIiKSwKICBFc3RpbWF0ZSA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkZXN0aW1hdGUpLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkbG93ZXJDTCksCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IGMocmVzX3RpbWVfbGFnX2VmZmVjdF91bmkkdXBwZXJDTCksCiAgYFZbYXV0aG9yc11gID0gYyh0aW1lX2xhZ19lZmZlY3RfdW5pJHNpZ21hMiwgTkEpLAogIGBSMmAgPSBjKHIyX3RpbWVfbGFnX2VmZmVjdF91bmlbMV0sIE5BKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKQpgYGAKIyMjIyBGaWd1cmUgUzQuMwpgYGB7ciwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9IDR9CnByZWRfdGltZV9sYWdfZWZmZWN0X3VuaSA8LXByZWRpY3Qucm1hKHRpbWVfbGFnX2VmZmVjdF91bmkpIAoKIyBwbG90dGluZwoKZml0X3RpbWVfbGFnX2VmZmVjdCA8LSAgZGF0ICU+JSAKICBtdXRhdGUoeW1pbiA9IHByZWRfdGltZV9sYWdfZWZmZWN0X3VuaSRjaS5sYiwgCiAgICAgICAgIHltYXggPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF91bmkkY2kudWIsCiAgICAgICAgIHltaW4yID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfdW5pJGNyLmxiLAogICAgICAgICB5bWF4MiA9IHByZWRfdGltZV9sYWdfZWZmZWN0X3VuaSRjci51YiwKICAgICAgICAgcHJlZCA9IHByZWRfdGltZV9sYWdfZWZmZWN0X3VuaSRwcmVkKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IFpyLCBzaXplID0gKDEvVlpyKSArIDMpKSArCiAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBmaWxsID0gImdyZXk5MCIpICsKICAjZ2VvbV9yaWJib24oYWVzKHltaW4gPSB5bWluLCB5bWF4ID0geW1heCksIGZpbGwgPSAiIzAwNzJCMiIpICArICMgbm90IHF1aXRlIHN1cmUgd2h5IHRoaXMgZG9lcyBub3Qgd29yawogIGdlb21fc21vb3RoKGFlcyh5ID0geW1pbjIpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0gICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgyKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICJkb3R0ZWQiLCBsd2QgPSAwLjI1LCBjb2xvdXIgPSAiIzAwNzJCMiIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4pLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSxsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltYXgpLCBtZXRob2QgPSAgImxvZXNzIiwgc2UgPSBGQUxTRSwgbHR5ID0iZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0iI0Q1NUUwMCIpICsgCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSBwcmVkKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRhc2hlZCIsIGx3ZCA9IDAuNSwgY29sb3VyID0iYmxhY2siKSArICAKICB5bGltKC0xLCAyKSArIHhsaW0oMTk5NCwyMDE5KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMTk5NSwgMjAwMCwgMjAwNSwgMjAxMCwgMjAxNSwgMjAyMCkpICsgCiAgI2dlb21fYWJsaW5lKGludGVyY2VwdCA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1sxXV0sIHNsb3BlID0gbXJfaG9zdF9yYW5nZV9saW5rX3JhdGlvJGJldGFbWzJdXSwgYWxwaGEgPSAwLjcsIGxpbmV0eXBlID0gImRhc2hlZCIsIHNpemUgPSAwLjUpICsKICBsYWJzKHggPSAiWWVhciIsIHkgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhaciksICIgKGVmZmVjdCBzaXplKSIpKSwgc2l6ZSA9IGV4cHJlc3Npb24ocGFzdGUoaXRhbGljKG4pLCAiICgjIG9mIHNwZWNpZXMgcGFpcnMpIikpKSArCiAgZ3VpZGVzKGZpbGwgPSAibm9uZSIsIGNvbG91ciA9ICJub25lIikgKwogICMgdGhlbXNlcwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0gYygwLCAxKSwgbGVnZW5kLmp1c3RpZmljYXRpb24gPSBjKDAsIDEpKSArCiAgdGhlbWUobGVnZW5kLmRpcmVjdGlvbj0iaG9yaXpvbnRhbCIpICsKICAjdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIsIGNvbG91ciA9ICJibGFjayIpKSArCiAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTAsIGNvbG91ciA9ImJsYWNrIiwgaGp1c3QgPSAwLjUsIGFuZ2xlID0gOTApKSAKCmZpdF90aW1lX2xhZ19lZmZlY3QKYGBgCgoqKkZpZ3VyZSBTNC4zOioqIEEgYnViYmxlIHBsb3Qgc2hvd2luZyBhIHByZWRpY3RlZCByZWdyZXNzaW9uIGxpbmUgZm9yIHRoZSBjb250ZW5pb3VzIHZhcmlhYmxlIGB5ZWFyYCwgaW5kaWNhdGluZyA5NSUgY29uZmlkZW5jZSByZWdpb25zIChvcmFuZ2UgZG90dGVkIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gcmVnaW9ucyAoYmx1ZSBkb3R0ZWQgbGluZXMpLCB3aXRoIG9ic2VydmVkIGVmZmVjdCBzaXplcyBiYXNlZCBvbiB2YXJpb3VzIHNhbXBsZSBzaXplcy4gCgojIyMjIE11bHRpdmFyaWF0ZSB0aW1lLWxhZyBiaWFzCmBgYHtyfQojIAp0aW1lX2xhZ19lZmZlY3RfbXVsIDwtIHJtYS5tdih5aSA9IFpyLCBWID0gVlpyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kcyA9IH4geWVhciArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgKwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvc3RfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2coaG9zdF9yYW5nZV9saW5rX3JhdGlvKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ltYmlvc2lzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYW5kb20gPSB+IDEgfCBhdXRob3JzLCBkYXRhID0gZGF0KQoKYGBgCgojIyMjIFRhYmxlIFM0LjQKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKEVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhwbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSBtZXRhLXJlZ3Jlc3Npb24gd2l0aCBgeWVhcmAuIApgYGB7cn0KIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3RpbWVfbGFnX2VmZmVjdF9tdWwgPC0gUjIodGltZV9sYWdfZWZmZWN0X211bCkKCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKCJJbnRlcmNlcHQgKGJvdGgtTWljcm9iZS1NdXR1YWxpc3QpIiwgIlllYXIiLCAiYm90aC1ob3Jpem9udGFsIiwgImJvdGgtdmVydGljYWwiLCAKICAgICAgICAgICAgICAgICAgICAgIk1pY3JvYmUtUGxhbnQiLCAiTWljcm9iZS1JbnZlcnQiLCAiTWljcm9iZS1WZXJ0IiwgImhvc3RfcmFuZ2UiLCAiTXV0dWFsaXN0LVBhcmFzaXRlIiksCiAgRXN0aW1hdGUgPSBjKHRpbWVfbGFnX2VmZmVjdF9tdWwkYiksCiAgYExvd2VyIENJIFswLjAyNV1gID0gYyh0aW1lX2xhZ19lZmZlY3RfbXVsJGNpLmxiKSwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gYyh0aW1lX2xhZ19lZmZlY3RfbXVsJGNpLnViKSwKICBgVlthdXRob3JzXWAgPSBjKHRpbWVfbGFnX2VmZmVjdF9tdWwkc2lnbWEyLCByZXAoTkEsOCkpLAogIGBSMmAgPSBjKHIyX3RpbWVfbGFnX2VmZmVjdF9tdWxbMV0sIHJlcChOQSw4KSkpICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikKYGBgCgojIyMjIEZpZ3VyZSBTNC40CmBgYHtyLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gNH0KcHJlZF90aW1lX2xhZ19lZmZlY3RfbXVsIDwtcHJlZGljdC5ybWEodGltZV9sYWdfZWZmZWN0X211bCkgCgojIHBsb3R0aW5nCmZpdF90aW1lX2xhZ19lZmZlY3RfbXVsIDwtICBkYXQgJT4lIAogIGZpbHRlcighaXMubmEobW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQpICYgIWlzLm5hKGhvc3RfdGF4X2Jyb2FkKSAmICFpcy5uYShzeW1iaW9zaXMpICYgIWlzLm5hKGhvc3RfcmFuZ2VfbGlua19yYXRpbykpICAlPiUgCiAgbXV0YXRlKHltaW4gPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkY2kubGIsIAogICAgICAgICB5bWF4ID0gcHJlZF90aW1lX2xhZ19lZmZlY3RfbXVsJGNpLnViLAogICAgICAgICB5bWluMiA9IHByZWRfdGltZV9sYWdfZWZmZWN0X211bCRjci5sYiwKICAgICAgICAgeW1heDIgPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkY3IudWIsCiAgICAgICAgIHByZWQgPSBwcmVkX3RpbWVfbGFnX2VmZmVjdF9tdWwkcHJlZCkgJT4lIAogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBaciwgc2l6ZSA9ICgxL1ZacikgKyAzKSkgKwogIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZmlsbCA9ICJncmV5OTAiKSArCiAgI2dlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gIiMwMDcyQjIiKSAgKyAjIG5vdCBxdWl0ZSBzdXJlIHdoeSB0aGlzIGRvZXMgbm90IHdvcmsKICBnZW9tX3Ntb290aChhZXMoeSA9IHltaW4yKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ICAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4MiksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSAiZG90dGVkIiwgbHdkID0gMC4yNSwgY29sb3VyID0gIiMwMDcyQjIiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWluKSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsbHR5ID0gImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArCiAgZ2VvbV9zbW9vdGgoYWVzKHkgPSB5bWF4KSwgbWV0aG9kID0gICJsb2VzcyIsIHNlID0gRkFMU0UsIGx0eSA9ImRvdHRlZCIsIGx3ZCA9IDAuMjUsIGNvbG91ciA9IiNENTVFMDAiKSArIAogIGdlb21fc21vb3RoKGFlcyh5ID0gcHJlZCksIG1ldGhvZCA9ICAibG9lc3MiLCBzZSA9IEZBTFNFLCBsdHkgPSJkYXNoZWQiLCBsd2QgPSAwLjUsIGNvbG91ciA9ImJsYWNrIikgKyAgCiAgeWxpbSgtMSwgMikgKyB4bGltKDE5OTQsMjAxOSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDE5OTUsIDIwMDAsIDIwMDUsIDIwMTAsIDIwMTUsIDIwMjApKSArIAogICNnZW9tX2FibGluZShpbnRlcmNlcHQgPSBtcl9ob3N0X3JhbmdlX2xpbmtfcmF0aW8kYmV0YVtbMV1dLCBzbG9wZSA9IG1yX2hvc3RfcmFuZ2VfbGlua19yYXRpbyRiZXRhW1syXV0sIGFscGhhID0gMC43LCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMC41KSArCiAgbGFicyh4ID0gIlllYXIiLCB5ID0gZXhwcmVzc2lvbihwYXN0ZShpdGFsaWMoWnIpLCAiIChlZmZlY3Qgc2l6ZSkiKSksIHNpemUgPSBleHByZXNzaW9uKHBhc3RlKGl0YWxpYyhuKSwgIiAoIyBvZiBzcGVjaWVzIHBhaXJzKSIpKSkgKwogIGd1aWRlcyhmaWxsID0gIm5vbmUiLCBjb2xvdXIgPSAibm9uZSIpICsKICAjIHRoZW1zZXMKICB0aGVtZV9idygpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb249IGMoMCwgMSksIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gYygwLCAxKSkgKwogIHRoZW1lKGxlZ2VuZC5kaXJlY3Rpb249Imhvcml6b250YWwiKSArCiAgI3RoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiLCBjb2xvdXIgPSAiYmxhY2siKSkgKwogIHRoZW1lKGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwLCBjb2xvdXIgPSJibGFjayIsIGhqdXN0ID0gMC41LCBhbmdsZSA9IDkwKSkgCgpmaXRfdGltZV9sYWdfZWZmZWN0X211bApgYGAKCioqRmlndXJlIFM0LjQ6KiogQSBidWJibGUgcGxvdCBzaG93aW5nIGEgcHJlZGljdGVkIGxvZXNzIGxpbmUgZm9yIHRoZSBjb250aW51b3VzIHZhcmlhYmxlIGB5ZWFyYCAoZ2l2ZW4gdGhlIHZhbHVlcyBvZiB0aGUgb3RoZXIgMyB2YXJpYWJsZXMgaW4gdGhlIG1vZGVsKSwgaW5kaWNhdGluZyA5NSUgY29uZmlkZW5jZSByZWdpb25zIChvcmFuZ2UgZG90dGVkIGxpbmVzKSBhbmQgOTUlIHByZWRpY3Rpb24gcmVnaW9ucyAoYmx1ZSBkb3R0ZWQgbGluZXMpIHdpdGggb2JzZXJ2ZWQgZWZmZWN0IHNpemVzIGJhc2VkIG9uIHZhcmlvdXMgc2FtcGxlIHNpemVzLiBOb3RlIHRoYXQgdGhlIGxpbmVzIGFyZSBub3QgbGluZWFyIGFzIHRoZXNlIGFyZSBiYXNlZCBvbiBtdWx0aXZhcmlhdGUgcHJlZGljdGlvbnMgb2YgdGhlIGRhdGEgcG9pbnRzLiAKCiMjIEFwcGVuZGl4IFM1OiBTZW5zaXRpdml0eSBBbmFseXNpcwoKVGhlIGZ1bm5lbCBwbG90cyBhYm92ZSBpZGVudGlmaWVkIHRoZSBpc3N1ZSBvZiB1cHBlciBib3VuZHMgZm9yIHRoZSBlZmZlY3Qgc2l6ZSBnaXZlbiBhIHNhbXBsZSBzaXplIChhbiB1cHBlciBsaW1pdCBvZiBhICpwKiB2YWx1ZSBnaXZlbiB0aGUgbnVtYmVyIG9mIHJhbmRvbWl6YXRpb25zKS4gVGhpcyBib3VuZGFyeSB3b3VsZCBpbmZsdWVuY2Ugb3VyIGVzdGltYXRlcyBvZiBtZWFuIGVmZmVjdCBzaXplcyBhbmQgY29udHJhc3RzIChpLmUuLCBjb21wYXJpbmcgdHdvIGdyb3VwcyksIG9mdGVuIG1ha2luZyBvdXIgb3ZlcmFsbCBjb25jbHVzaW9ucyB0b28gY29uc2VydmF0aXZlLiBUbyBkZW1vbnN0cmF0ZSB0aGlzLCB3ZSBjb25kdWN0ZWQgdHdvIGFuYWx5c2VzIHRvIHNob3c6IDEpICB0aGUgbnVtYmVyIG9mIHJhbmRvbWl6YXRpb25zIChgbG9nKG5vX3JhbmRvbWl6YXRpb25zKWApIGRvIG5vdCBkaWZmZXIgYmV0d2VlbiBjYXRlZ29yaWVzIGluIHRoZSAzIGltcG9ydGFudCBjYXRlZ29yaWNhbCBtb2RlcmF0b3JzIChgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBgaG9zdF90YXhfYnJvYWRgLCAmIGBzeW1iaW9zaXNgKSwgYW5kLCAyKSBjYXRlZ29yaWVzIHdpdGggaGlnaCBlZmZlY3Qgc2l6ZXMgd291bGQgaW5jbHVkZSAiYm91bmRlZCIgZWZmZWN0IHNpemVzIChpLmUuLCBmcm9tICpwKiA9IDAuMDEsIDAuMDAxLCBvciAwLjAwMDE7IGBsaW1pdF9yZWFjaGVkYCkgaW4gdGhlIDMgbW9kZXJhdG9ycy4KCiMjIyBTZW5zaXRpdml0eSB0ZXN0IDE6IHRoZSBudW1iZXIgb2YgcmFuZG9taXphdGlvbnMKCkJlbG93LCB3ZSBzaG93ZWQgdGhhdCBub25lIG9mIHRoZSBjYXRlZ29yaWVzIGhhdmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgbnVtYmVycyBvZiByYW5kb21pemF0aW9ucyBpbiBhbGwgYG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkYCwgYGhvc3RfdGF4X2Jyb2FkYCwgJiBgc3ltYmlvc2lzYC4gCiAKIyMjIyBUaGUgdHlwZSBvZiBzeW1iaW9zaXM6IHBhcmFzaXRpc20gdnMuIG11dHVhbGlzbQoKYGBge3J9CiMgMjMzIC0tLSBZZXMgPSA3NCAoMC4zMTc1OTY2JSk7IE5vID0gMTU5CgojIHN5bWJpb3NpcwojIG11bHRpcGxlIGludGVyY2VwdHMKc2FfcmFuZG9tX3N5bWJpb3NpczE8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IHN5bWJpb3NpcyAtIDEgKyAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQojY29udHJhc3QKc2FfcmFuZG9tX3N5bWJpb3NpczI8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IHN5bWJpb3NpcyArICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCgpgYGAKCiMjIyMgVGFibGUgUzUuMQpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoRXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpLCBmcm9tIHRoZSByZWdyZXNzaW9uIHdpdGggYHN5bWJpb3Npc2Agb24gYGxvZyhub19yYW5kb21pemF0aW9ucylgLiAKCmBgYHtyfQojIGdldHRpbmcgbWFyZ2luYWwgUjIKcjJfc2FfcmFuZG9tX3N5bWJpb3NpcyA8LSByMl9uYWthZ2F3YShzYV9yYW5kb21fc3ltYmlvc2lzMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzPC0gdGliYmxlKGVzdGlhbXRlID0gYyhmaXhlZihzYV9yYW5kb21fc3ltYmlvc2lzMSksIGZpeGVmKHNhX3JhbmRvbV9zeW1iaW9zaXMyKVsyXSkpCgpjaV9zYV9yYW5kb21fc3ltYmlvc2lzMTwtY29uZmludChzYV9yYW5kb21fc3ltYmlvc2lzMSkKY2lfc2FfcmFuZG9tX3N5bWJpb3NpczI8LWNvbmZpbnQoc2FfcmFuZG9tX3N5bWJpb3NpczIpCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSBjKGNpX3NhX3JhbmRvbV9zeW1iaW9zaXMxWzM6NCwxXSwgY2lfc2FfcmFuZG9tX3N5bWJpb3NpczJbNCwxXSkpCnJlc19zYV9yYW5kb21fc3ltYmlvc2lzICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSBjKGNpX3NhX3JhbmRvbV9zeW1iaW9zaXMxWzM6NCwyXSwgY2lfc2FfcmFuZG9tX3N5bWJpb3NpczJbNCwyXSkpCiAgICAgICAgICAgCiMgY3JlYXRpbmcgYSB0YWJsZQp0aWJibGUoCiAgYEZpeGVkIGVmZmVjdGAgPSBjKGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvc2lzMSRuYW1lKSwgY29udF9nZW4ocmVzX3N5bWJpb3NpczEkbmFtZSkpLAogIEVzdGltYXRlID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkZXN0aWFtdGUsCiAgYExvd2VyIENJIFswLjAyNV1gID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkbG93ZXJDTCwKICBgVXBwZXIgQ0kgIFswLjk3NV1gID0gcmVzX3NhX3JhbmRvbV9zeW1iaW9zaXMkdXBwZXJDTCwKICBgVlthdXRob3JzXWAgPSBjKGF0dHIoVmFyQ29ycihzYV9yYW5kb21fc3ltYmlvc2lzMSkkYXV0aG9yLCJzdGRkZXYiKV4yLCAgcmVwKE5BLCAyKSksCiAgYFZbcmVzaWR1YWxzXWAgPWMoYXR0cihWYXJDb3JyKHNhX3JhbmRvbV9zeW1iaW9zaXMxKSwic2MiKV4yLCByZXAoTkEsIDIpKSwKICBgUjJgID0gYyhyMl9zYV9yYW5kb21fc3ltYmlvc2lzJFIyX21hcmdpbmFsLCByZXAoTkEsIDIpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCiMjIyMgVGhlIGVmZmVjdCBvZiBob3N0IHRheGEKYGBge3J9CiMgaG9zdF90YXhfYnJvYWQKIyBtdXRpcGxlIGludGVyY2VwdHMKc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMTwtbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gaG9zdF90YXhfYnJvYWQgLSAxICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfCBhdXRob3JzKSwgZGF0YSA9IGRhdCkKIyBjb250cmFzdCAxCnNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDI8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IGhvc3RfdGF4X2Jyb2FkICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICgxIHwgYXV0aG9ycyksIGRhdGEgPSBkYXQpCiMgY29udHJhc3QgMgpzYV9yYW5kb21faG9zdF90YXhfYnJvYWQzPC1sbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiByZWxldmVsKGhvc3RfdGF4X2Jyb2FkLCByZWYgPSAiUGxhbnQiKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQoKIyBjb250cmFzdCAzCnNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDQ8LWxtZXIobG9nKG5vX3JhbmRvbWl6YXRpb25zKSB+IHJlbGV2ZWwoaG9zdF90YXhfYnJvYWQsIHJlZiA9ICJJbnZlcnQiKSArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfCBhdXRob3JzKSwgZGF0YSA9IGRhdCkKYGBgCgojIyMjIFRhYmxlIFM1LjIKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKGVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhwbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSByZWdyZXNzaW9uIHdpdGggYGhvc3RfdGF4X2Jyb2FkYCBvbiBgbG9nKG5vX3JhbmRvbWl6YXRpb25zKWAuIAoKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQgPC0gcjJfbmFrYWdhd2Eoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCA8LSB0aWJibGUoZXN0aWFtdGUgPSBjKGZpeGVmKHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmKHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDIpWzI6NF0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZihzYV9yYW5kb21faG9zdF90YXhfYnJvYWQzKVszOjRdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZml4ZWYoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkNClbNF0pKSAKICAKY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMTwtY29uZmludChzYV9yYW5kb21faG9zdF90YXhfYnJvYWQxKQpjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQyPC1jb25maW50KHNhX3JhbmRvbV9ob3N0X3RheF9icm9hZDIpCmNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDM8LWNvbmZpbnQoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMykKY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkNDwtY29uZmludChzYV9yYW5kb21faG9zdF90YXhfYnJvYWQ0KQpyZXNfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSBjKGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDFbMzo2LDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMls0OjYsMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDNbNTo2LDFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQ0WzYsMV0pKQpyZXNfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSBjKGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDFbMzo2LDJdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMls0OjYsMl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZDNbNTo2LDJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21faG9zdF90YXhfYnJvYWQ0WzYsMl0pKQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gIGMoYXMuY2hhcmFjdGVyKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJG5hbWUpLCBjb250X2dlbihyZXNfc3ltYmlvbnRfdGF4X2Jyb2FkMSRuYW1lKSksICMgZG9uZQogIEVzdGltYXRlID0gcmVzX3NhX3JhbmRvbV9ob3N0X3RheF9icm9hZCRlc3RpYW10ZSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSByZXNfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkJGxvd2VyQ0wsCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IHJlc19zYV9yYW5kb21faG9zdF90YXhfYnJvYWQkdXBwZXJDTCwKICBgVlthdXRob3JzXWAgPSBjKGF0dHIoVmFyQ29ycihzYV9yYW5kb21faG9zdF90YXhfYnJvYWQxKSRhdXRob3IsInN0ZGRldiIpXjIsICByZXAoTkEsIDkpKSwKICBgVltyZXNpZHVhbHNdYCA9YyhhdHRyKFZhckNvcnIoc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkMSksInNjIileMiwgcmVwKE5BLCA5KSksCiAgYFIyYCA9IGMocjJfc2FfcmFuZG9tX2hvc3RfdGF4X2Jyb2FkJFIyX21hcmdpbmFsLCByZXAoTkEsIDkpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgojIyMjIFRoZSBlZmZlY3Qgb2YgdGhlIG1vZGUgb2YgdHJhbnNtaXNzaW9uCgpgYGB7cn0KIyBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZAoKc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMTwtbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgLSAxICsgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQoKCiMgY29udHJhc3QgMQpzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQyPC1sbWVyKGxvZyhub19yYW5kb21pemF0aW9ucykgfiBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCArIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMSB8IGF1dGhvcnMpLCBkYXRhID0gZGF0KQoKIyBjb250cmFzdCAyCnNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDMgPC0gbG1lcihsb2cobm9fcmFuZG9taXphdGlvbnMpIH4gcmVsZXZlbChtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCwgcmVmID0gInZlcnRpY2FsIikgKyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKDEgfCBhdXRob3JzKSwgZGF0YSA9IGRhdCkKYGBgCgojIyMjIFRhYmxlIFM1LjMKUmVncmVzc2lvbiBjb2VmZmljaWVudHMgKGVzdGltYXRlKSwgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIChDSXMpLCB2YXJpYW5jZSBjb21wb25lbnRzIChWKSBhbmQgdmFyaWFuY2UgZXhwbGFpbmVkLCAqUipeMl5+W21hcmdpbmFsXX4gKFIyKSBmcm9tIHRoZSByZWdyZXNzaW9uIHdpdGggYG1vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkYCBvbiBgbG9nKG5vX3JhbmRvbWl6YXRpb25zKWAuIAoKYGBge3J9CiMgZ2V0dGluZyBtYXJnaW5hbCBSMgpyMl9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgPC0gcjJfbmFrYWdhd2Eoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCA8LSB0aWJibGUoZXN0aWFtdGUgPSBjKGZpeGVmKHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpeGVmKHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDIpWzI6M10sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaXhlZihzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQzKVszXSkpIAogIApjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxPC1jb25maW50KHNhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpCmNpX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDI8LWNvbmZpbnQoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMikKY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMzwtY29uZmludChzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQzKQpyZXNfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSBjKGNpX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDFbMzo1LDFdLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMls0OjUsMV0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDNbNSwxXSkpCnJlc19zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQgJTw+JSBtdXRhdGUodXBwZXJDTCA9IGMoY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMVszOjUsMl0sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaV9zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQyWzQ6NSwyXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2lfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkM1s1LDJdKSkKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGMoYXMuY2hhcmFjdGVyKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkbmFtZSksIGNvbnRfZ2VuKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkbmFtZSkpLAogIEVzdGltYXRlID0gcmVzX3NhX3JhbmRvbV9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCRlc3RpYW10ZSwKICBgTG93ZXIgQ0kgWzAuMDI1XWAgPSByZXNfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkJGxvd2VyQ0wsCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IHJlc19zYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkdXBwZXJDTCwKICBgVlthdXRob3JzXWAgPSBjKGF0dHIoVmFyQ29ycihzYV9yYW5kb21fbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSRhdXRob3IsInN0ZGRldiIpXjIsICByZXAoTkEsIDUpKSwKICBgVltyZXNpZHVhbHNdYCA9YyhhdHRyKFZhckNvcnIoc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSksInNjIileMiwgcmVwKE5BLCA1KSksCiAgYFIyYCA9IGMocjJfc2FfcmFuZG9tX21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkJFIyX21hcmdpbmFsLCByZXAoTkEsIDUpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKYGBgCgojIyMgU2Vuc2l0aXZpdHkgdGVzdCAyOiByZWFjaGluZyB0aGUgbGltaXRzCgpCZWxvdywgd2Ugc2hvdyB0aGF0IGNhdGVnb3JpZXMgd2l0aCBoaWdoZXIgZWZmZWN0IHNpemVzIHdlcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSAiYm91bmRlZCIgZWZmZWN0IHNpemVzIChgbGltaXRfcmVhY2hlZGApIGluIGFsbCBgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWRgLCBgaG9zdF90YXhfYnJvYWRgLCAmIGBzeW1iaW9zaXNgLiBUaGlzIGluZGljYXRlcyB0aGF0IHRoZSBoaWdoZXIgdGhlIGVzdGltYXRlIG9mIG1lYW4gZWZmZWN0IHNpemUgaXMsIHRoZSBtb3JlIHVuZGVyZXN0aW1hdGVkIHRoZSBtZWFuIGVmZmVjdCBzaXplIGlzLiBUaGlzIGlzIHRydWUgZm9yIGRpZmZlcmVuY2VzIGJldHdlZW4gdHdvIGNhdGVnb3JpZXM7IHRoZSBsYXJnZXIgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvLCB0aGUgbW9yZSB1bmRlcmVzdGltYXRlZCB0aGUgZGlmZmVyZW5jZSBpcy4gCgoKIyMjIyBUaGUgdHlwZSBvZiBzeW1iaW9zaXM6IHBhcmFzaXRpc20gdnMuIG11dHVhbGlzbQoKIyMjIyBUYWJsZSBTNS40ClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChlc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgcmVncmVzc2lvbiB3aXRoIGBzeW1iaW9zaXNgIG9uIGBsaW1pdF9yZWFjaGVkYCAoY29tcGFyZSB0aGUgZWZmZWN0IGVzdGltYXRlcyBpbiAqKlRhYmxlIFMzLjEqKiB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyBpbiB0aGlzIHRhYmxlIGJlbG93OyB0aGVpciByYW5raW5nIGluIGVzdGltYXRpb24gc2hvdWxkIHVzdWFsbHkgbWF0Y2gpLgoKYGBge3J9CiMgc3ltYmlvc2lzCnNhX2xpbWl0X3N5bWJpb3NpczEgPC0gZ2xtZXIobGltaXRfcmVhY2hlZCB+IHN5bWJpb3NpcyAtIDEgKyAoMSB8IGF1dGhvcnMpLCBmYW1pbHkgPSAiYmlub21pYWwiLCBkYXRhID0gZGF0KQoKIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3NhX2xpbWl0X3N5bWJpb3NpcyA8LSByMl9uYWthZ2F3YShzYV9saW1pdF9zeW1iaW9zaXMxKQoKIyBnZXR0aW5nIGVzdGltYXRlcwpyZXNfc2FfbGltaXRfc3ltYmlvc2lzIDwtIHRpYmJsZShlc3RpYW10ZSA9IGZpeGVmKHNhX2xpbWl0X3N5bWJpb3NpczEpKQogIApyZXNfc2FfbGltaXRfc3ltYmlvc2lzICU8PiUgbXV0YXRlKGxvd2VyQ0wgPSAodGlkeShzYV9saW1pdF9zeW1iaW9zaXMxKSRlc3RpbWF0ZVstM10gLQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkeShzYV9saW1pdF9zeW1iaW9zaXMxKSRzdGQuZXJyb3JbLTNdKnFub3JtKDAuOTc1KSkpCnJlc19zYV9saW1pdF9zeW1iaW9zaXMgJTw+JSBtdXRhdGUodXBwZXJDTCA9ICh0aWR5KHNhX2xpbWl0X3N5bWJpb3NpczEpJGVzdGltYXRlWy0zXSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWR5KHNhX2xpbWl0X3N5bWJpb3NpczEpJHN0ZC5lcnJvclstM10qcW5vcm0oMC45NzUpKSkKIyBjcmVhdGluZyBhIHRhYmxlCnRpYmJsZSgKICBgRml4ZWQgZWZmZWN0YCA9IGFzLmNoYXJhY3RlcihyZXNfc3ltYmlvc2lzMSRuYW1lKSwKICBFc3RpbWF0ZSA9IHJlc19zYV9saW1pdF9zeW1iaW9zaXMkZXN0aWFtdGUsCiAgYExvd2VyIENJIFswLjAyNV1gID0gcmVzX3NhX2xpbWl0X3N5bWJpb3NpcyRsb3dlckNMLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSByZXNfc2FfbGltaXRfc3ltYmlvc2lzJHVwcGVyQ0wsCiAgYFZbYXV0aG9yc11gID0gYyhhdHRyKFZhckNvcnIoc2FfbGltaXRfc3ltYmlvc2lzMSkkYXV0aG9yLCJzdGRkZXYiKV4yLCAgcmVwKE5BLCAxKSksCiAgYFIyYCA9IGMocjJfc2FfbGltaXRfc3ltYmlvc2lzJFIyX21hcmdpbmFsLCByZXAoTkEsIDEpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKCiN0X3N5bWJpb3NpcwoKYGBgCiMjIyMgVGFibGUgUzMuMSogKGZvciBjb21wYXJpc2lvbikKSW4gYm90aCB0YWJsZXMsIGBtdXR1YWxpc3RgIGhhcyBoaWdoZXIgZXN0aW1hdGVzIChpLmUsIGBtdXR1YWxpc3RgIHJlYXJjaGVkIHRoZSBjZWlsaW5nIG1vcmUgb2Z0ZW4pIAoKYGBge3J9CnRfc3ltYmlvc2lzICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKCiMjIyMgVGhlIGVmZmVjdCBvZiBob3N0IHRheGEKCiMjIyMgVGFibGUgUzUuNQpSZWdyZXNzaW9uIGNvZWZmaWNpZW50cyAoZXN0aW1hdGUpLCA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcyksIHZhcmlhbmNlIGNvbXBvbmVudHMgKFYpIGFuZCB2YXJpYW5jZSBleHBsYWluZWQsICpSKl4yXn5bbWFyZ2luYWxdfiAoUjIpIGZyb20gdGhlIHJlZ3Jlc3Npb24gd2l0aCBgaG9zdF90YXhfYnJvYWRgIG9uIGBsaW1pdF9yZWFjaGVkYCAgKGNvbXBhcmUgdGhlIGVmZmVjdCBlc3RpbWF0ZXMgaW4gKipUYWJsZSBTMy4yKiogd2l0aCB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMgaW4gdGhpcyB0YWJsZSBiZWxvdzsgdGhlaXIgcmFua2luZyBpbiBlc3RpbWF0aW9uIHNob3VsZCB1c3VhbGx5IG1hdGNoKS4KCmBgYHtyfQojIGhvc3RfdGF4X2Jyb2FkCnNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMTwtZ2xtZXIobGltaXRfcmVhY2hlZCB+IGhvc3RfdGF4X2Jyb2FkIC0gMSAgKyAoMSB8IGF1dGhvcnMpLCBmYW1pbHkgPSAiYmlub21pYWwiLCBkYXRhID0gZGF0KQoKIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkIDwtIHIyX25ha2FnYXdhKHNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkIDwtIHRpYmJsZShlc3RpYW10ZSA9IGZpeGVmKHNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMSkpCiAgCnJlc19zYV9saW1pdF9ob3N0X3RheF9icm9hZCAlPD4lIG11dGF0ZShsb3dlckNMID0gKHRpZHkoc2FfbGltaXRfaG9zdF90YXhfYnJvYWQxKSRlc3RpbWF0ZVstNV0gLQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkeShzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpJHN0ZC5lcnJvclstNV0qcW5vcm0oMC45NzUpKSkKcmVzX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSAodGlkeShzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpJGVzdGltYXRlWy01XSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWR5KHNhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkMSkkc3RkLmVycm9yWy01XSpxbm9ybSgwLjk3NSkpKQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYXMuY2hhcmFjdGVyKHJlc19zeW1iaW9udF90YXhfYnJvYWQxJG5hbWUpLAogIEVzdGltYXRlID0gcmVzX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkJGVzdGlhbXRlLAogIGBMb3dlciBDSSBbMC4wMjVdYCA9IHJlc19zYV9saW1pdF9ob3N0X3RheF9icm9hZCRsb3dlckNMLAogIGBVcHBlciBDSSAgWzAuOTc1XWAgPSByZXNfc2FfbGltaXRfaG9zdF90YXhfYnJvYWQkdXBwZXJDTCwKICBgVlthdXRob3JzXWAgPSBjKGF0dHIoVmFyQ29ycihzYV9saW1pdF9ob3N0X3RheF9icm9hZDEpJGF1dGhvciwic3RkZGV2IileMiwgIHJlcChOQSwgMykpLAogIGBSMmAgPSBjKHIyX3NhX2xpbWl0X2hvc3RfdGF4X2Jyb2FkJFIyX21hcmdpbmFsLCByZXAoTkEsIDMpKSkgJT4lIGthYmxlKCJodG1sIiwgZGlnaXRzID0gMykgJT4lCiAga2FibGVfc3R5bGluZygic3RyaXBlZCIsIHBvc2l0aW9uID0gImxlZnQiKSAKCiMgdF9ob3N0X3RheAoKYGBgCiMjIyMgVGFibGUgUzMuMiogKGZvciBjb21wYXJpc2lvbikKCmBgYHtyfQp0X2hvc3RfdGF4ICU+JSBrYWJsZSgiaHRtbCIsIGRpZ2l0cyA9IDMpICU+JQogIGthYmxlX3N0eWxpbmcoInN0cmlwZWQiLCBwb3NpdGlvbiA9ICJsZWZ0IikgCmBgYAoKIyMjIyBUaGUgZWZmZWN0IG9mIHRoZSBtb2RlIG9mIHRyYW5zbWlzc2lvbgoKIyMjIyBUYWJsZSBTNS42ClJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIChlc3RpbWF0ZSksIDk1JSBjb25maWRlbmNlIGludGVydmFscyAoQ0lzKSwgdmFyaWFuY2UgY29tcG9uZW50cyAoVikgYW5kIHZhcmlhbmNlIGV4cGxhaW5lZCwgKlIqXjJeflttYXJnaW5hbF1+IChSMikgZnJvbSB0aGUgcmVncmVzc2lvbiB3aXRoIGBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZGAgb24gYGxpbWl0X3JlYWNoZWRgICAoY29tcGFyZSB0aGUgZWZmZWN0IGVzdGltYXRlcyBpbiAqKlRhYmxlIFMzLjcqKiB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyBpbiB0aGlzIHRhYmxlIGJlbG93OyB0aGVpciByYW5raW5nIGluIGVzdGltYXRpb24gc2hvdWxkIHVzdWFsbHkgbWF0Y2gpLgoKYGBge3J9CiMgbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQKc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxIDwtIGdsbWVyKGxpbWl0X3JlYWNoZWQgfiBtb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAtIDEgKyAoMSB8IGF1dGhvcnMpLCBmYW1pbHkgPSAiYmlub21pYWwiLCBkYXRhID0gZGF0KQoKIyBnZXR0aW5nIG1hcmdpbmFsIFIyCnIyX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIDwtIHIyX25ha2FnYXdhKHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkKCiMgZ2V0dGluZyBlc3RpbWF0ZXMKcmVzX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkIDwtIHRpYmJsZShlc3RpYW10ZSA9IGZpeGVmKHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkpCiAgCnJlc19zYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCAlPD4lIG11dGF0ZShsb3dlckNMID0gKHRpZHkoc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQxKSRlc3RpbWF0ZVstNF0gLQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGlkeShzYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpJHN0ZC5lcnJvclstNF0qcW5vcm0oMC45NzUpKSkKcmVzX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkICU8PiUgbXV0YXRlKHVwcGVyQ0wgPSAodGlkeShzYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEpJGVzdGltYXRlWy00XSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aWR5KHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkkc3RkLmVycm9yWy00XSpxbm9ybSgwLjk3NSkpKQojIGNyZWF0aW5nIGEgdGFibGUKdGliYmxlKAogIGBGaXhlZCBlZmZlY3RgID0gYXMuY2hhcmFjdGVyKHJlc19tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZDEkbmFtZSksCiAgRXN0aW1hdGUgPSByZXNfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkZXN0aWFtdGUsCiAgYExvd2VyIENJIFswLjAyNV1gID0gcmVzX3NhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkJGxvd2VyQ0wsCiAgYFVwcGVyIENJICBbMC45NzVdYCA9IHJlc19zYV9saW1pdF9tb2RlX29mX3RyYW5zbWlzc2lvbl9icm9hZCR1cHBlckNMLAogIGBWW2F1dGhvcnNdYCA9IGMoYXR0cihWYXJDb3JyKHNhX2xpbWl0X21vZGVfb2ZfdHJhbnNtaXNzaW9uX2Jyb2FkMSkkYXV0aG9yLCJzdGRkZXYiKV4yLCAgcmVwKE5BLCAyKSksCiAgYFIyYCA9IGMocjJfc2FfbGltaXRfbW9kZV9vZl90cmFuc21pc3Npb25fYnJvYWQkUjJfbWFyZ2luYWwsIHJlcChOQSwgMikpKSAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpIAoKIyB0X3RyYW5zbWlzc2lvbgpgYGAKCiMjIyMgVGFibGUgUzMuNyogKGZvciBjb21wYXJpc2lvbikKCmBgYHtyfQp0X3RyYW5zbWlzc2lvbiAlPiUga2FibGUoImh0bWwiLCBkaWdpdHMgPSAzKSAlPiUKICBrYWJsZV9zdHlsaW5nKCJzdHJpcGVkIiwgcG9zaXRpb24gPSAibGVmdCIpIApgYGAKCiMjIEFja25vd2xlZGdlbWVudHMKCk1hbnkgY29kaW5nIG1hdGVyaWFscyBoYXZlIGJlZW4gYm9ycm93ZWQgZnJvbSB0aGVzZSBwYXBlcnMgW0BjYWxseTIwMTltZXRhOyBAb2RlYTIwMThkZXZlbG9wbWVudGFsXS4gV2UgdGhhbmsgTG9zaWEgTGFnaXN6IGZvciBwcmVwYXJpbmcgc21hbGwgaWNvbnMgYW5kIGNhcnRvb25zIHVzZWQgaW4gdGhlIGZpZ3VyZXMuIAoKIyMgUiBTZXNzaW9uIEluZm9ybWF0aW9uCgpgYGB7cn0KIyBwYW5kZXIgZm9yIG1ha2luZyBpdCBsb29rIG5pY2VyCnNlc3Npb25JbmZvKCkgJT4lIHBhbmRlcigpCmBgYAoKIyMgUmVmZXJlbmNlcw==